1c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* libFLAC - Free Lossless Audio Codec library 2c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson 3c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 4c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Redistribution and use in source and binary forms, with or without 5c74663799493f2b1e6123c18def94295d0afab7Kenny Root * modification, are permitted provided that the following conditions 6c74663799493f2b1e6123c18def94295d0afab7Kenny Root * are met: 7c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 8c74663799493f2b1e6123c18def94295d0afab7Kenny Root * - Redistributions of source code must retain the above copyright 9c74663799493f2b1e6123c18def94295d0afab7Kenny Root * notice, this list of conditions and the following disclaimer. 10c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 11c74663799493f2b1e6123c18def94295d0afab7Kenny Root * - Redistributions in binary form must reproduce the above copyright 12c74663799493f2b1e6123c18def94295d0afab7Kenny Root * notice, this list of conditions and the following disclaimer in the 13c74663799493f2b1e6123c18def94295d0afab7Kenny Root * documentation and/or other materials provided with the distribution. 14c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 15c74663799493f2b1e6123c18def94295d0afab7Kenny Root * - Neither the name of the Xiph.org Foundation nor the names of its 16c74663799493f2b1e6123c18def94295d0afab7Kenny Root * contributors may be used to endorse or promote products derived from 17c74663799493f2b1e6123c18def94295d0afab7Kenny Root * this software without specific prior written permission. 18c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 19c74663799493f2b1e6123c18def94295d0afab7Kenny Root * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20c74663799493f2b1e6123c18def94295d0afab7Kenny Root * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21c74663799493f2b1e6123c18def94295d0afab7Kenny Root * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22c74663799493f2b1e6123c18def94295d0afab7Kenny Root * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 23c74663799493f2b1e6123c18def94295d0afab7Kenny Root * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24c74663799493f2b1e6123c18def94295d0afab7Kenny Root * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25c74663799493f2b1e6123c18def94295d0afab7Kenny Root * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26c74663799493f2b1e6123c18def94295d0afab7Kenny Root * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27c74663799493f2b1e6123c18def94295d0afab7Kenny Root * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28c74663799493f2b1e6123c18def94295d0afab7Kenny Root * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29c74663799493f2b1e6123c18def94295d0afab7Kenny Root * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 31c74663799493f2b1e6123c18def94295d0afab7Kenny Root 32c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if HAVE_CONFIG_H 33c74663799493f2b1e6123c18def94295d0afab7Kenny Root# include <config.h> 34c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 35c74663799493f2b1e6123c18def94295d0afab7Kenny Root 36c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <errno.h> 37c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <stdio.h> 38c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <stdlib.h> 39c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <string.h> 40c74663799493f2b1e6123c18def94295d0afab7Kenny Root 41c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ 42c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined __BORLANDC__ 43c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <utime.h> /* for utime() */ 44c74663799493f2b1e6123c18def94295d0afab7Kenny Root#else 45c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <sys/utime.h> /* for utime() */ 46c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 47c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <io.h> /* for chmod() */ 48c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <sys/types.h> /* for off_t */ 49c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if _MSC_VER <= 1600 || defined __BORLANDC__ /* @@@ [2G limit] */ 50c74663799493f2b1e6123c18def94295d0afab7Kenny Root#define fseeko fseek 51c74663799493f2b1e6123c18def94295d0afab7Kenny Root#define ftello ftell 52c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 53c74663799493f2b1e6123c18def94295d0afab7Kenny Root#else 54c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */ 55c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <utime.h> /* for utime() */ 56c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <unistd.h> /* for chown(), unlink() */ 57c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 58c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include <sys/stat.h> /* for stat(), maybe chmod() */ 59c74663799493f2b1e6123c18def94295d0afab7Kenny Root 60c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include "private/metadata.h" 61c74663799493f2b1e6123c18def94295d0afab7Kenny Root 62c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include "FLAC/assert.h" 63c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include "FLAC/stream_decoder.h" 64c74663799493f2b1e6123c18def94295d0afab7Kenny Root#include "share/alloc.h" 65c74663799493f2b1e6123c18def94295d0afab7Kenny Root 66c74663799493f2b1e6123c18def94295d0afab7Kenny Root#ifdef max 67c74663799493f2b1e6123c18def94295d0afab7Kenny Root#undef max 68c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 69c74663799493f2b1e6123c18def94295d0afab7Kenny Root#define max(a,b) ((a)>(b)?(a):(b)) 70c74663799493f2b1e6123c18def94295d0afab7Kenny Root#ifdef min 71c74663799493f2b1e6123c18def94295d0afab7Kenny Root#undef min 72c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 73c74663799493f2b1e6123c18def94295d0afab7Kenny Root#define min(a,b) ((a)<(b)?(a):(b)) 74c74663799493f2b1e6123c18def94295d0afab7Kenny Root 75c74663799493f2b1e6123c18def94295d0afab7Kenny Root 76c74663799493f2b1e6123c18def94295d0afab7Kenny Root/**************************************************************************** 77c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 78c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Local function declarations 79c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 80c74663799493f2b1e6123c18def94295d0afab7Kenny Root ***************************************************************************/ 81c74663799493f2b1e6123c18def94295d0afab7Kenny Root 82c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes); 83c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes); 84c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes); 85c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes); 86c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes); 87c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes); 88c74663799493f2b1e6123c18def94295d0afab7Kenny Root 89c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator); 90c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block); 91c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length); 92c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block); 93c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block); 94c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length); 95c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length); 96c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length); 97c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry); 98c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block); 99c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track); 100c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block); 101c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block); 102c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length); 103c74663799493f2b1e6123c18def94295d0afab7Kenny Root 104c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); 105c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); 106c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block); 107c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block); 108c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block); 109c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length); 110c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length); 111c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block); 112c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block); 113c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block); 114c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block); 115c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length); 116c74663799493f2b1e6123c18def94295d0afab7Kenny Root 117c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block); 118c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last); 119c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append); 120c74663799493f2b1e6123c18def94295d0afab7Kenny Root 121c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator); 122c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator); 123c74663799493f2b1e6123c18def94295d0afab7Kenny Root 124c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb); 125c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic unsigned seek_to_first_metadata_block_(FILE *f); 126c74663799493f2b1e6123c18def94295d0afab7Kenny Root 127c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append); 128c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, off_t fixup_is_last_flag_offset, FLAC__bool backup); 129c74663799493f2b1e6123c18def94295d0afab7Kenny Root 130c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status); 131c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic 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, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status); 132c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status); 133c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic 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); 134c74663799493f2b1e6123c18def94295d0afab7Kenny Root 135c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status); 136c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status); 137c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void cleanup_tempfile_(FILE **tempfile, char **tempfilename); 138c74663799493f2b1e6123c18def94295d0afab7Kenny Root 139c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool get_file_stats_(const char *filename, struct stat *stats); 140c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void set_file_stats_(const char *filename, struct stat *stats); 141c74663799493f2b1e6123c18def94295d0afab7Kenny Root 142c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence); 143c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle); 144c74663799493f2b1e6123c18def94295d0afab7Kenny Root 145c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status); 146c74663799493f2b1e6123c18def94295d0afab7Kenny Root 147c74663799493f2b1e6123c18def94295d0afab7Kenny Root 148c74663799493f2b1e6123c18def94295d0afab7Kenny Root#ifdef FLAC__VALGRIND_TESTING 149c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 150c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 151c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t ret = fwrite(ptr, size, nmemb, stream); 152c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!ferror(stream)) 153c74663799493f2b1e6123c18def94295d0afab7Kenny Root fflush(stream); 154c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 155c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 156c74663799493f2b1e6123c18def94295d0afab7Kenny Root#else 157c74663799493f2b1e6123c18def94295d0afab7Kenny Root#define local__fwrite fwrite 158c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 159c74663799493f2b1e6123c18def94295d0afab7Kenny Root 160c74663799493f2b1e6123c18def94295d0afab7Kenny Root/**************************************************************************** 161c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 162c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Level 0 implementation 163c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 164c74663799493f2b1e6123c18def94295d0afab7Kenny Root ***************************************************************************/ 165c74663799493f2b1e6123c18def94295d0afab7Kenny Root 166c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); 167c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); 168c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); 169c74663799493f2b1e6123c18def94295d0afab7Kenny Root 170c74663799493f2b1e6123c18def94295d0afab7Kenny Roottypedef struct { 171c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool got_error; 172c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata *object; 173c74663799493f2b1e6123c18def94295d0afab7Kenny Root} level0_client_data; 174c74663799493f2b1e6123c18def94295d0afab7Kenny Root 175c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type) 176c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 177c74663799493f2b1e6123c18def94295d0afab7Kenny Root level0_client_data cd; 178c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamDecoder *decoder; 179c74663799493f2b1e6123c18def94295d0afab7Kenny Root 180c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 181c74663799493f2b1e6123c18def94295d0afab7Kenny Root 182c74663799493f2b1e6123c18def94295d0afab7Kenny Root cd.got_error = false; 183c74663799493f2b1e6123c18def94295d0afab7Kenny Root cd.object = 0; 184c74663799493f2b1e6123c18def94295d0afab7Kenny Root 185c74663799493f2b1e6123c18def94295d0afab7Kenny Root decoder = FLAC__stream_decoder_new(); 186c74663799493f2b1e6123c18def94295d0afab7Kenny Root 187c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == decoder) 188c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0; 189c74663799493f2b1e6123c18def94295d0afab7Kenny Root 190c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_set_md5_checking(decoder, false); 191c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_set_metadata_ignore_all(decoder); 192c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_set_metadata_respond(decoder, type); 193c74663799493f2b1e6123c18def94295d0afab7Kenny Root 194c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &cd) != FLAC__STREAM_DECODER_INIT_STATUS_OK || cd.got_error) { 195c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)FLAC__stream_decoder_finish(decoder); 196c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_delete(decoder); 197c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0; 198c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 199c74663799493f2b1e6123c18def94295d0afab7Kenny Root 200c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || cd.got_error) { 201c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)FLAC__stream_decoder_finish(decoder); 202c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_delete(decoder); 203c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != cd.object) 204c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(cd.object); 205c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0; 206c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 207c74663799493f2b1e6123c18def94295d0afab7Kenny Root 208c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)FLAC__stream_decoder_finish(decoder); 209c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_delete(decoder); 210c74663799493f2b1e6123c18def94295d0afab7Kenny Root 211c74663799493f2b1e6123c18def94295d0afab7Kenny Root return cd.object; 212c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 213c74663799493f2b1e6123c18def94295d0afab7Kenny Root 214c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo) 215c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 216c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata *object; 217c74663799493f2b1e6123c18def94295d0afab7Kenny Root 218c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 219c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != streaminfo); 220c74663799493f2b1e6123c18def94295d0afab7Kenny Root 221c74663799493f2b1e6123c18def94295d0afab7Kenny Root object = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_STREAMINFO); 222c74663799493f2b1e6123c18def94295d0afab7Kenny Root 223c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (object) { 224c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* can just copy the contents since STREAMINFO has no internal structure */ 225c74663799493f2b1e6123c18def94295d0afab7Kenny Root *streaminfo = *object; 226c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(object); 227c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 228c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 229c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 230c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 231c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 232c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 233c74663799493f2b1e6123c18def94295d0afab7Kenny Root 234c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags) 235c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 236c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 237c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != tags); 238c74663799493f2b1e6123c18def94295d0afab7Kenny Root 239c74663799493f2b1e6123c18def94295d0afab7Kenny Root *tags = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_VORBIS_COMMENT); 240c74663799493f2b1e6123c18def94295d0afab7Kenny Root 241c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0 != *tags; 242c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 243c74663799493f2b1e6123c18def94295d0afab7Kenny Root 244c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet) 245c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 246c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 247c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != cuesheet); 248c74663799493f2b1e6123c18def94295d0afab7Kenny Root 249c74663799493f2b1e6123c18def94295d0afab7Kenny Root *cuesheet = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_CUESHEET); 250c74663799493f2b1e6123c18def94295d0afab7Kenny Root 251c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0 != *cuesheet; 252c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 253c74663799493f2b1e6123c18def94295d0afab7Kenny Root 254c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) 255c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 256c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)decoder, (void)frame, (void)buffer, (void)client_data; 257c74663799493f2b1e6123c18def94295d0afab7Kenny Root 258c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; 259c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 260c74663799493f2b1e6123c18def94295d0afab7Kenny Root 261c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) 262c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 263c74663799493f2b1e6123c18def94295d0afab7Kenny Root level0_client_data *cd = (level0_client_data *)client_data; 264c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)decoder; 265c74663799493f2b1e6123c18def94295d0afab7Kenny Root 266c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* 267c74663799493f2b1e6123c18def94295d0afab7Kenny Root * we assume we only get here when the one metadata block we were 268c74663799493f2b1e6123c18def94295d0afab7Kenny Root * looking for was passed to us 269c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 270c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!cd->got_error && 0 == cd->object) { 271c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (cd->object = FLAC__metadata_object_clone(metadata))) 272c74663799493f2b1e6123c18def94295d0afab7Kenny Root cd->got_error = true; 273c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 274c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 275c74663799493f2b1e6123c18def94295d0afab7Kenny Root 276c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) 277c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 278c74663799493f2b1e6123c18def94295d0afab7Kenny Root level0_client_data *cd = (level0_client_data *)client_data; 279c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)decoder; 280c74663799493f2b1e6123c18def94295d0afab7Kenny Root 281c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) 282c74663799493f2b1e6123c18def94295d0afab7Kenny Root cd->got_error = true; 283c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 284c74663799493f2b1e6123c18def94295d0afab7Kenny Root 285c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_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) 286c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 287c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIterator *it; 288c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__uint64 max_area_seen = 0; 289c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__uint64 max_depth_seen = 0; 290c74663799493f2b1e6123c18def94295d0afab7Kenny Root 291c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 292c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != picture); 293c74663799493f2b1e6123c18def94295d0afab7Kenny Root 294c74663799493f2b1e6123c18def94295d0afab7Kenny Root *picture = 0; 295c74663799493f2b1e6123c18def94295d0afab7Kenny Root 296c74663799493f2b1e6123c18def94295d0afab7Kenny Root it = FLAC__metadata_simple_iterator_new(); 297c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == it) 298c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 299c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) { 300c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_simple_iterator_delete(it); 301c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 302c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 303c74663799493f2b1e6123c18def94295d0afab7Kenny Root do { 304c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) { 305c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it); 306c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height; 307c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* check constraints */ 308c74663799493f2b1e6123c18def94295d0afab7Kenny Root if( 309c74663799493f2b1e6123c18def94295d0afab7Kenny Root (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) && 310c74663799493f2b1e6123c18def94295d0afab7Kenny Root (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) && 311c74663799493f2b1e6123c18def94295d0afab7Kenny Root (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) && 312c74663799493f2b1e6123c18def94295d0afab7Kenny Root obj->data.picture.width <= max_width && 313c74663799493f2b1e6123c18def94295d0afab7Kenny Root obj->data.picture.height <= max_height && 314c74663799493f2b1e6123c18def94295d0afab7Kenny Root obj->data.picture.depth <= max_depth && 315c74663799493f2b1e6123c18def94295d0afab7Kenny Root obj->data.picture.colors <= max_colors && 316c74663799493f2b1e6123c18def94295d0afab7Kenny Root (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen)) 317c74663799493f2b1e6123c18def94295d0afab7Kenny Root ) { 318c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(*picture) 319c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(*picture); 320c74663799493f2b1e6123c18def94295d0afab7Kenny Root *picture = obj; 321c74663799493f2b1e6123c18def94295d0afab7Kenny Root max_area_seen = area; 322c74663799493f2b1e6123c18def94295d0afab7Kenny Root max_depth_seen = obj->data.picture.depth; 323c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 324c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 325c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(obj); 326c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 327c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 328c74663799493f2b1e6123c18def94295d0afab7Kenny Root } while(FLAC__metadata_simple_iterator_next(it)); 329c74663799493f2b1e6123c18def94295d0afab7Kenny Root 330c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_simple_iterator_delete(it); 331c74663799493f2b1e6123c18def94295d0afab7Kenny Root 332c74663799493f2b1e6123c18def94295d0afab7Kenny Root return (0 != *picture); 333c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 334c74663799493f2b1e6123c18def94295d0afab7Kenny Root 335c74663799493f2b1e6123c18def94295d0afab7Kenny Root 336c74663799493f2b1e6123c18def94295d0afab7Kenny Root/**************************************************************************** 337c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 338c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Level 1 implementation 339c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 340c74663799493f2b1e6123c18def94295d0afab7Kenny Root ***************************************************************************/ 341c74663799493f2b1e6123c18def94295d0afab7Kenny Root 342c74663799493f2b1e6123c18def94295d0afab7Kenny Root#define SIMPLE_ITERATOR_MAX_PUSH_DEPTH (1+4) 343c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* 1 for initial offset, +4 for our own personal use */ 344c74663799493f2b1e6123c18def94295d0afab7Kenny Root 345c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstruct FLAC__Metadata_SimpleIterator { 346c74663799493f2b1e6123c18def94295d0afab7Kenny Root FILE *file; 347c74663799493f2b1e6123c18def94295d0afab7Kenny Root char *filename, *tempfile_path_prefix; 348c74663799493f2b1e6123c18def94295d0afab7Kenny Root struct stat stats; 349c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool has_stats; 350c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool is_writable; 351c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIteratorStatus status; 352c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH]; 353c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t first_offset; /* this is the offset to the STREAMINFO block */ 354c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned depth; 355c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* this is the metadata block header of the current block we are pointing to: */ 356c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool is_last; 357c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__MetadataType type; 358c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned length; 359c74663799493f2b1e6123c18def94295d0afab7Kenny Root}; 360c74663799493f2b1e6123c18def94295d0afab7Kenny Root 361c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[] = { 362c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK", 363c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT", 364c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE", 365c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE", 366c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE", 367c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA", 368c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR", 369c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR", 370c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR", 371c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR", 372c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR", 373c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR", 374c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR" 375c74663799493f2b1e6123c18def94295d0afab7Kenny Root}; 376c74663799493f2b1e6123c18def94295d0afab7Kenny Root 377c74663799493f2b1e6123c18def94295d0afab7Kenny Root 378c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void) 379c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 380c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIterator *iterator = (FLAC__Metadata_SimpleIterator*)calloc(1, sizeof(FLAC__Metadata_SimpleIterator)); 381c74663799493f2b1e6123c18def94295d0afab7Kenny Root 382c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != iterator) { 383c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->file = 0; 384c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->filename = 0; 385c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->tempfile_path_prefix = 0; 386c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->has_stats = false; 387c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->is_writable = false; 388c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 389c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->first_offset = iterator->offset[0] = -1; 390c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->depth = 0; 391c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 392c74663799493f2b1e6123c18def94295d0afab7Kenny Root 393c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator; 394c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 395c74663799493f2b1e6123c18def94295d0afab7Kenny Root 396c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void simple_iterator_free_guts_(FLAC__Metadata_SimpleIterator *iterator) 397c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 398c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 399c74663799493f2b1e6123c18def94295d0afab7Kenny Root 400c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != iterator->file) { 401c74663799493f2b1e6123c18def94295d0afab7Kenny Root fclose(iterator->file); 402c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->file = 0; 403c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->has_stats) 404c74663799493f2b1e6123c18def94295d0afab7Kenny Root set_file_stats_(iterator->filename, &iterator->stats); 405c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 406c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != iterator->filename) { 407c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(iterator->filename); 408c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->filename = 0; 409c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 410c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != iterator->tempfile_path_prefix) { 411c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(iterator->tempfile_path_prefix); 412c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->tempfile_path_prefix = 0; 413c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 414c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 415c74663799493f2b1e6123c18def94295d0afab7Kenny Root 416c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator) 417c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 418c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 419c74663799493f2b1e6123c18def94295d0afab7Kenny Root 420c74663799493f2b1e6123c18def94295d0afab7Kenny Root simple_iterator_free_guts_(iterator); 421c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(iterator); 422c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 423c74663799493f2b1e6123c18def94295d0afab7Kenny Root 424c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator) 425c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 426c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIteratorStatus status; 427c74663799493f2b1e6123c18def94295d0afab7Kenny Root 428c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 429c74663799493f2b1e6123c18def94295d0afab7Kenny Root 430c74663799493f2b1e6123c18def94295d0afab7Kenny Root status = iterator->status; 431c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 432c74663799493f2b1e6123c18def94295d0afab7Kenny Root return status; 433c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 434c74663799493f2b1e6123c18def94295d0afab7Kenny Root 435c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool read_only) 436c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 437c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned ret; 438c74663799493f2b1e6123c18def94295d0afab7Kenny Root 439c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 440c74663799493f2b1e6123c18def94295d0afab7Kenny Root 441c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_only || 0 == (iterator->file = fopen(iterator->filename, "r+b"))) { 442c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->is_writable = false; 443c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_only || errno == EACCES) { 444c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (iterator->file = fopen(iterator->filename, "rb"))) { 445c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; 446c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 447c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 448c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 449c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 450c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; 451c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 452c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 453c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 454c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 455c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->is_writable = true; 456c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 457c74663799493f2b1e6123c18def94295d0afab7Kenny Root 458c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = seek_to_first_metadata_block_(iterator->file); 459c74663799493f2b1e6123c18def94295d0afab7Kenny Root switch(ret) { 460c74663799493f2b1e6123c18def94295d0afab7Kenny Root case 0: 461c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->depth = 0; 462c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->first_offset = iterator->offset[iterator->depth] = ftello(iterator->file); 463c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_header_(iterator); 464c74663799493f2b1e6123c18def94295d0afab7Kenny Root case 1: 465c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 466c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 467c74663799493f2b1e6123c18def94295d0afab7Kenny Root case 2: 468c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 469c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 470c74663799493f2b1e6123c18def94295d0afab7Kenny Root case 3: 471c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE; 472c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 473c74663799493f2b1e6123c18def94295d0afab7Kenny Root default: 474c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0); 475c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 476c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 477c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 478c74663799493f2b1e6123c18def94295d0afab7Kenny Root 479c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if 0 480c74663799493f2b1e6123c18def94295d0afab7Kenny Root@@@ If we decide to finish implementing this, put this comment back in metadata.h 481c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* 482c74663799493f2b1e6123c18def94295d0afab7Kenny Root * The 'tempfile_path_prefix' allows you to specify a directory where 483c74663799493f2b1e6123c18def94295d0afab7Kenny Root * tempfiles should go. Remember that if your metadata edits cause the 484c74663799493f2b1e6123c18def94295d0afab7Kenny Root * FLAC file to grow, the entire file will have to be rewritten. If 485c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 'tempfile_path_prefix' is NULL, the temp file will be written in the 486c74663799493f2b1e6123c18def94295d0afab7Kenny Root * same directory as the original FLAC file. This makes replacing the 487c74663799493f2b1e6123c18def94295d0afab7Kenny Root * original with the tempfile fast but requires extra space in the same 488c74663799493f2b1e6123c18def94295d0afab7Kenny Root * partition for the tempfile. If space is a problem, you can pass a 489c74663799493f2b1e6123c18def94295d0afab7Kenny Root * directory name belonging to a different partition in 490c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 'tempfile_path_prefix'. Note that you should use the forward slash 491c74663799493f2b1e6123c18def94295d0afab7Kenny Root * '/' as the directory separator. A trailing slash is not needed; it 492c74663799493f2b1e6123c18def94295d0afab7Kenny Root * will be added automatically. 493c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 494c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats, const char *tempfile_path_prefix); 495c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 496c74663799493f2b1e6123c18def94295d0afab7Kenny Root 497c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool read_only, FLAC__bool preserve_file_stats) 498c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 499c74663799493f2b1e6123c18def94295d0afab7Kenny Root const char *tempfile_path_prefix = 0; /*@@@ search for comments near 'rename(...)' for what it will take to finish implementing this */ 500c74663799493f2b1e6123c18def94295d0afab7Kenny Root 501c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 502c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 503c74663799493f2b1e6123c18def94295d0afab7Kenny Root 504c74663799493f2b1e6123c18def94295d0afab7Kenny Root simple_iterator_free_guts_(iterator); 505c74663799493f2b1e6123c18def94295d0afab7Kenny Root 506c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!read_only && preserve_file_stats) 507c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->has_stats = get_file_stats_(filename, &iterator->stats); 508c74663799493f2b1e6123c18def94295d0afab7Kenny Root 509c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (iterator->filename = strdup(filename))) { 510c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 511c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 512c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 513c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != tempfile_path_prefix && 0 == (iterator->tempfile_path_prefix = strdup(tempfile_path_prefix))) { 514c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 515c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 516c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 517c74663799493f2b1e6123c18def94295d0afab7Kenny Root 518c74663799493f2b1e6123c18def94295d0afab7Kenny Root return simple_iterator_prime_input_(iterator, read_only); 519c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 520c74663799493f2b1e6123c18def94295d0afab7Kenny Root 521c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator *iterator) 522c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 523c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 524c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 525c74663799493f2b1e6123c18def94295d0afab7Kenny Root 526c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator->is_writable; 527c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 528c74663799493f2b1e6123c18def94295d0afab7Kenny Root 529c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator *iterator) 530c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 531c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 532c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 533c74663799493f2b1e6123c18def94295d0afab7Kenny Root 534c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->is_last) 535c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 536c74663799493f2b1e6123c18def94295d0afab7Kenny Root 537c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) { 538c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 539c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 540c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 541c74663799493f2b1e6123c18def94295d0afab7Kenny Root 542c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->offset[iterator->depth] = ftello(iterator->file); 543c74663799493f2b1e6123c18def94295d0afab7Kenny Root 544c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_header_(iterator); 545c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 546c74663799493f2b1e6123c18def94295d0afab7Kenny Root 547c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator) 548c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 549c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t this_offset; 550c74663799493f2b1e6123c18def94295d0afab7Kenny Root 551c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 552c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 553c74663799493f2b1e6123c18def94295d0afab7Kenny Root 554c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->offset[iterator->depth] == iterator->first_offset) 555c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 556c74663799493f2b1e6123c18def94295d0afab7Kenny Root 557c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->first_offset, SEEK_SET)) { 558c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 559c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 560c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 561c74663799493f2b1e6123c18def94295d0afab7Kenny Root this_offset = iterator->first_offset; 562c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!read_metadata_block_header_(iterator)) 563c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 564c74663799493f2b1e6123c18def94295d0afab7Kenny Root 565c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* we ignore any error from ftello() and catch it in fseeko() */ 566c74663799493f2b1e6123c18def94295d0afab7Kenny Root while(ftello(iterator->file) + (off_t)iterator->length < iterator->offset[iterator->depth]) { 567c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) { 568c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 569c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 570c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 571c74663799493f2b1e6123c18def94295d0afab7Kenny Root this_offset = ftello(iterator->file); 572c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!read_metadata_block_header_(iterator)) 573c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 574c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 575c74663799493f2b1e6123c18def94295d0afab7Kenny Root 576c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->offset[iterator->depth] = this_offset; 577c74663799493f2b1e6123c18def94295d0afab7Kenny Root 578c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 579c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 580c74663799493f2b1e6123c18def94295d0afab7Kenny Root 581c74663799493f2b1e6123c18def94295d0afab7Kenny Root/*@@@@add to tests*/ 582c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_last(const FLAC__Metadata_SimpleIterator *iterator) 583c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 584c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 585c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 586c74663799493f2b1e6123c18def94295d0afab7Kenny Root 587c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator->is_last; 588c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 589c74663799493f2b1e6123c18def94295d0afab7Kenny Root 590c74663799493f2b1e6123c18def94295d0afab7Kenny Root/*@@@@add to tests*/ 591c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API off_t FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metadata_SimpleIterator *iterator) 592c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 593c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 594c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 595c74663799493f2b1e6123c18def94295d0afab7Kenny Root 596c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator->offset[iterator->depth]; 597c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 598c74663799493f2b1e6123c18def94295d0afab7Kenny Root 599c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator) 600c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 601c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 602c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 603c74663799493f2b1e6123c18def94295d0afab7Kenny Root 604c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator->type; 605c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 606c74663799493f2b1e6123c18def94295d0afab7Kenny Root 607c74663799493f2b1e6123c18def94295d0afab7Kenny Root/*@@@@add to tests*/ 608c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator) 609c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 610c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 611c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 612c74663799493f2b1e6123c18def94295d0afab7Kenny Root 613c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator->length; 614c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 615c74663799493f2b1e6123c18def94295d0afab7Kenny Root 616c74663799493f2b1e6123c18def94295d0afab7Kenny Root/*@@@@add to tests*/ 617c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_get_application_id(FLAC__Metadata_SimpleIterator *iterator, FLAC__byte *id) 618c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 619c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; 620c74663799493f2b1e6123c18def94295d0afab7Kenny Root 621c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 622c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 623c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != id); 624c74663799493f2b1e6123c18def94295d0afab7Kenny Root 625c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->type != FLAC__METADATA_TYPE_APPLICATION) { 626c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; 627c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 628c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 629c74663799493f2b1e6123c18def94295d0afab7Kenny Root 630c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(fread(id, 1, id_bytes, iterator->file) != id_bytes) { 631c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 632c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 633c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 634c74663799493f2b1e6123c18def94295d0afab7Kenny Root 635c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* back up */ 636c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, -((int)id_bytes), SEEK_CUR)) { 637c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 638c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 639c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 640c74663799493f2b1e6123c18def94295d0afab7Kenny Root 641c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 642c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 643c74663799493f2b1e6123c18def94295d0afab7Kenny Root 644c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator) 645c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 646c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata *block = FLAC__metadata_object_new(iterator->type); 647c74663799493f2b1e6123c18def94295d0afab7Kenny Root 648c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 649c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 650c74663799493f2b1e6123c18def94295d0afab7Kenny Root 651c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != block) { 652c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_last = iterator->is_last; 653c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->length = iterator->length; 654c74663799493f2b1e6123c18def94295d0afab7Kenny Root 655c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!read_metadata_block_data_(iterator, block)) { 656c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(block); 657c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0; 658c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 659c74663799493f2b1e6123c18def94295d0afab7Kenny Root 660c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* back up to the beginning of the block data to stay consistent */ 661c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) { 662c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 663c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(block); 664c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0; 665c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 666c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 667c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 668c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 669c74663799493f2b1e6123c18def94295d0afab7Kenny Root 670c74663799493f2b1e6123c18def94295d0afab7Kenny Root return block; 671c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 672c74663799493f2b1e6123c18def94295d0afab7Kenny Root 673c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding) 674c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 675c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth];) 676c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool ret; 677c74663799493f2b1e6123c18def94295d0afab7Kenny Root 678c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 679c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 680c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != block); 681c74663799493f2b1e6123c18def94295d0afab7Kenny Root 682c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!iterator->is_writable) { 683c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE; 684c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 685c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 686c74663799493f2b1e6123c18def94295d0afab7Kenny Root 687c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO || block->type == FLAC__METADATA_TYPE_STREAMINFO) { 688c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->type != block->type) { 689c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; 690c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 691c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 692c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 693c74663799493f2b1e6123c18def94295d0afab7Kenny Root 694c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_last = iterator->is_last; 695c74663799493f2b1e6123c18def94295d0afab7Kenny Root 696c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->length == block->length) 697c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_stationary_(iterator, block); 698c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(iterator->length > block->length) { 699c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) { 700c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last); 701c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 702c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 703c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 704c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 705c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 706c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = rewrite_whole_file_(iterator, block, /*append=*/false); 707c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 708c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 709c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 710c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 711c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 712c74663799493f2b1e6123c18def94295d0afab7Kenny Root else /* iterator->length < block->length */ { 713c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned padding_leftover = 0; 714c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool padding_is_last = false; 715c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(use_padding) { 716c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* first see if we can even use padding */ 717c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->is_last) { 718c74663799493f2b1e6123c18def94295d0afab7Kenny Root use_padding = false; 719c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 720c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 721c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned extra_padding_bytes_required = block->length - iterator->length; 722c74663799493f2b1e6123c18def94295d0afab7Kenny Root simple_iterator_push_(iterator); 723c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__metadata_simple_iterator_next(iterator)) { 724c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)simple_iterator_pop_(iterator); 725c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 726c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 727c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->type != FLAC__METADATA_TYPE_PADDING) { 728c74663799493f2b1e6123c18def94295d0afab7Kenny Root use_padding = false; 729c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 730c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 731c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length == extra_padding_bytes_required) { 732c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding_leftover = 0; 733c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_last = iterator->is_last; 734c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 735c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(iterator->length < extra_padding_bytes_required) 736c74663799493f2b1e6123c18def94295d0afab7Kenny Root use_padding = false; 737c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 738c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding_leftover = FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length - extra_padding_bytes_required; 739c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding_is_last = iterator->is_last; 740c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_last = false; 741c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 742c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 743c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!simple_iterator_pop_(iterator)) 744c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 745c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 746c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 747c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(use_padding) { 748c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(padding_leftover == 0) { 749c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = write_metadata_block_stationary_(iterator, block); 750c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 751c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 752c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 753c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 754c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 755c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH); 756c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last); 757c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 758c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 759c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 760c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 761c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 762c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 763c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = rewrite_whole_file_(iterator, block, /*append=*/false); 764c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); 765c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 766c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 767c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 768c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 769c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 770c74663799493f2b1e6123c18def94295d0afab7Kenny Root 771c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding) 772c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 773c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned padding_leftover = 0; 774c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool padding_is_last = false; 775c74663799493f2b1e6123c18def94295d0afab7Kenny Root 776c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;) 777c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool ret; 778c74663799493f2b1e6123c18def94295d0afab7Kenny Root 779c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 780c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 781c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != block); 782c74663799493f2b1e6123c18def94295d0afab7Kenny Root 783c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!iterator->is_writable) 784c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 785c74663799493f2b1e6123c18def94295d0afab7Kenny Root 786c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block->type == FLAC__METADATA_TYPE_STREAMINFO) { 787c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; 788c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 789c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 790c74663799493f2b1e6123c18def94295d0afab7Kenny Root 791c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_last = iterator->is_last; 792c74663799493f2b1e6123c18def94295d0afab7Kenny Root 793c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(use_padding) { 794c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* first see if we can even use padding */ 795c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->is_last) { 796c74663799493f2b1e6123c18def94295d0afab7Kenny Root use_padding = false; 797c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 798c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 799c74663799493f2b1e6123c18def94295d0afab7Kenny Root simple_iterator_push_(iterator); 800c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__metadata_simple_iterator_next(iterator)) { 801c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)simple_iterator_pop_(iterator); 802c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 803c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 804c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->type != FLAC__METADATA_TYPE_PADDING) { 805c74663799493f2b1e6123c18def94295d0afab7Kenny Root use_padding = false; 806c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 807c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 808c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->length == block->length) { 809c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding_leftover = 0; 810c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_last = iterator->is_last; 811c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 812c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(iterator->length < FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) 813c74663799493f2b1e6123c18def94295d0afab7Kenny Root use_padding = false; 814c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 815c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding_leftover = iterator->length - block->length; 816c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding_is_last = iterator->is_last; 817c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_last = false; 818c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 819c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 820c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!simple_iterator_pop_(iterator)) 821c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 822c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 823c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 824c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(use_padding) { 825c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* move to the next block, which is suitable padding */ 826c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__metadata_simple_iterator_next(iterator)) 827c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 828c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(padding_leftover == 0) { 829c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = write_metadata_block_stationary_(iterator, block); 830c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); 831c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 832c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 833c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 834c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 835c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH); 836c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last); 837c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); 838c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 839c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 840c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 841c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 842c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 843c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = rewrite_whole_file_(iterator, block, /*append=*/true); 844c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); 845c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); 846c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 847c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 848c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 849c74663799493f2b1e6123c18def94295d0afab7Kenny Root 850c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding) 851c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 852c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth];) 853c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool ret; 854c74663799493f2b1e6123c18def94295d0afab7Kenny Root 855c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) { 856c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; 857c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 858c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 859c74663799493f2b1e6123c18def94295d0afab7Kenny Root 860c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(use_padding) { 861c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata *padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING); 862c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == padding) { 863c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 864c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 865c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 866c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding->length = iterator->length; 867c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false)) { 868c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(padding); 869c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 870c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 871c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(padding); 872c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__metadata_simple_iterator_prev(iterator)) 873c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 874c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length == debug_target_offset); 875c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(ftello(iterator->file) + (off_t)iterator->length == debug_target_offset); 876c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 877c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 878c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 879c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = rewrite_whole_file_(iterator, 0, /*append=*/false); 880c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length == debug_target_offset); 881c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(ftello(iterator->file) + (off_t)iterator->length == debug_target_offset); 882c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 883c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 884c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 885c74663799493f2b1e6123c18def94295d0afab7Kenny Root 886c74663799493f2b1e6123c18def94295d0afab7Kenny Root 887c74663799493f2b1e6123c18def94295d0afab7Kenny Root 888c74663799493f2b1e6123c18def94295d0afab7Kenny Root/**************************************************************************** 889c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 890c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Level 2 implementation 891c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 892c74663799493f2b1e6123c18def94295d0afab7Kenny Root ***************************************************************************/ 893c74663799493f2b1e6123c18def94295d0afab7Kenny Root 894c74663799493f2b1e6123c18def94295d0afab7Kenny Root 895c74663799493f2b1e6123c18def94295d0afab7Kenny Roottypedef struct FLAC__Metadata_Node { 896c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata *data; 897c74663799493f2b1e6123c18def94295d0afab7Kenny Root struct FLAC__Metadata_Node *prev, *next; 898c74663799493f2b1e6123c18def94295d0afab7Kenny Root} FLAC__Metadata_Node; 899c74663799493f2b1e6123c18def94295d0afab7Kenny Root 900c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstruct FLAC__Metadata_Chain { 901c74663799493f2b1e6123c18def94295d0afab7Kenny Root char *filename; /* will be NULL if using callbacks */ 902c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool is_ogg; 903c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *head; 904c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *tail; 905c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned nodes; 906c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_ChainStatus status; 907c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t first_offset, last_offset; 908c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* 909c74663799493f2b1e6123c18def94295d0afab7Kenny Root * This is the length of the chain initially read from the FLAC file. 910c74663799493f2b1e6123c18def94295d0afab7Kenny Root * it is used to compare against the current length to decide whether 911c74663799493f2b1e6123c18def94295d0afab7Kenny Root * or not the whole file has to be rewritten. 912c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 913c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t initial_length; 914c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* @@@ hacky, these are currently only needed by ogg reader */ 915c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__IOHandle handle; 916c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__IOCallback_Read read_cb; 917c74663799493f2b1e6123c18def94295d0afab7Kenny Root}; 918c74663799493f2b1e6123c18def94295d0afab7Kenny Root 919c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstruct FLAC__Metadata_Iterator { 920c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Chain *chain; 921c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *current; 922c74663799493f2b1e6123c18def94295d0afab7Kenny Root}; 923c74663799493f2b1e6123c18def94295d0afab7Kenny Root 924c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API const char * const FLAC__Metadata_ChainStatusString[] = { 925c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_OK", 926c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT", 927c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE", 928c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE", 929c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE", 930c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA", 931c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_READ_ERROR", 932c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR", 933c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR", 934c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR", 935c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR", 936c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR", 937c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR", 938c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS", 939c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", 940c74663799493f2b1e6123c18def94295d0afab7Kenny Root "FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL" 941c74663799493f2b1e6123c18def94295d0afab7Kenny Root}; 942c74663799493f2b1e6123c18def94295d0afab7Kenny Root 943c74663799493f2b1e6123c18def94295d0afab7Kenny Root 944c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_Node *node_new_(void) 945c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 946c74663799493f2b1e6123c18def94295d0afab7Kenny Root return (FLAC__Metadata_Node*)calloc(1, sizeof(FLAC__Metadata_Node)); 947c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 948c74663799493f2b1e6123c18def94295d0afab7Kenny Root 949c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void node_delete_(FLAC__Metadata_Node *node) 950c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 951c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != node); 952c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != node->data) 953c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(node->data); 954c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(node); 955c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 956c74663799493f2b1e6123c18def94295d0afab7Kenny Root 957c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void chain_init_(FLAC__Metadata_Chain *chain) 958c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 959c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 960c74663799493f2b1e6123c18def94295d0afab7Kenny Root 961c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->filename = 0; 962c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->is_ogg = false; 963c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->head = chain->tail = 0; 964c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->nodes = 0; 965c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_OK; 966c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->initial_length = 0; 967c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->read_cb = 0; 968c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 969c74663799493f2b1e6123c18def94295d0afab7Kenny Root 970c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void chain_clear_(FLAC__Metadata_Chain *chain) 971c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 972c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node, *next; 973c74663799493f2b1e6123c18def94295d0afab7Kenny Root 974c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 975c74663799493f2b1e6123c18def94295d0afab7Kenny Root 976c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(node = chain->head; node; ) { 977c74663799493f2b1e6123c18def94295d0afab7Kenny Root next = node->next; 978c74663799493f2b1e6123c18def94295d0afab7Kenny Root node_delete_(node); 979c74663799493f2b1e6123c18def94295d0afab7Kenny Root node = next; 980c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 981c74663799493f2b1e6123c18def94295d0afab7Kenny Root 982c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != chain->filename) 983c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(chain->filename); 984c74663799493f2b1e6123c18def94295d0afab7Kenny Root 985c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_init_(chain); 986c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 987c74663799493f2b1e6123c18def94295d0afab7Kenny Root 988c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void chain_append_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) 989c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 990c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 991c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != node); 992c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != node->data); 993c74663799493f2b1e6123c18def94295d0afab7Kenny Root 994c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->next = node->prev = 0; 995c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data->is_last = true; 996c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != chain->tail) 997c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->tail->data->is_last = false; 998c74663799493f2b1e6123c18def94295d0afab7Kenny Root 999c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == chain->head) 1000c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->head = node; 1001c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 1002c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain->tail); 1003c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->tail->next = node; 1004c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->prev = chain->tail; 1005c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1006c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->tail = node; 1007c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->nodes++; 1008c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1009c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1010c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void chain_remove_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) 1011c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1012c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1013c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != node); 1014c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1015c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(node == chain->head) 1016c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->head = node->next; 1017c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 1018c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->prev->next = node->next; 1019c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1020c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(node == chain->tail) 1021c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->tail = node->prev; 1022c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 1023c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->next->prev = node->prev; 1024c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1025c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != chain->tail) 1026c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->tail->data->is_last = true; 1027c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1028c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->nodes--; 1029c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1030c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1031c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void chain_delete_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) 1032c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1033c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_remove_node_(chain, node); 1034c74663799493f2b1e6123c18def94295d0afab7Kenny Root node_delete_(node); 1035c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1036c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1037c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic off_t chain_calculate_length_(FLAC__Metadata_Chain *chain) 1038c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1039c74663799493f2b1e6123c18def94295d0afab7Kenny Root const FLAC__Metadata_Node *node; 1040c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t length = 0; 1041c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(node = chain->head; node; node = node->next) 1042c74663799493f2b1e6123c18def94295d0afab7Kenny Root length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); 1043c74663799493f2b1e6123c18def94295d0afab7Kenny Root return length; 1044c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1045c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1046c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void iterator_insert_node_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node) 1047c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1048c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != node); 1049c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != node->data); 1050c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1051c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->current); 1052c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->chain); 1053c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->chain->head); 1054c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->chain->tail); 1055c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1056c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data->is_last = false; 1057c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1058c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->prev = iterator->current->prev; 1059c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->next = iterator->current; 1060c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1061c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == node->prev) 1062c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->chain->head = node; 1063c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 1064c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->prev->next = node; 1065c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1066c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current->prev = node; 1067c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1068c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->chain->nodes++; 1069c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1070c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1071c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void iterator_insert_node_after_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node) 1072c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1073c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != node); 1074c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != node->data); 1075c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1076c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->current); 1077c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->chain); 1078c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->chain->head); 1079c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->chain->tail); 1080c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1081c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current->data->is_last = false; 1082c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1083c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->prev = iterator->current; 1084c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->next = iterator->current->next; 1085c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1086c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == node->next) 1087c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->chain->tail = node; 1088c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 1089c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->next->prev = node; 1090c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1091c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->prev->next = node; 1092c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1093c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->chain->tail->data->is_last = true; 1094c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1095c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->chain->nodes++; 1096c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1097c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1098c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* return true iff node and node->next are both padding */ 1099c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool chain_merge_adjacent_padding_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) 1100c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1101c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(node->data->type == FLAC__METADATA_TYPE_PADDING && 0 != node->next && node->next->data->type == FLAC__METADATA_TYPE_PADDING) { 1102c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned growth = FLAC__STREAM_METADATA_HEADER_LENGTH + node->next->data->length; 1103c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data->length += growth; 1104c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1105c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_delete_node_(chain, node->next); 1106c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1107c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1108c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 1109c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1110c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1111c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1112c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* Returns the new length of the chain, or 0 if there was an error. */ 1113c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* WATCHOUT: This can get called multiple times before a write, so 1114c74663799493f2b1e6123c18def94295d0afab7Kenny Root * it should still work when this happens. 1115c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 1116c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* WATCHOUT: Make sure to also update the logic in 1117c74663799493f2b1e6123c18def94295d0afab7Kenny Root * FLAC__metadata_chain_check_if_tempfile_needed() if the logic here changes. 1118c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 1119c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic off_t chain_prepare_for_write_(FLAC__Metadata_Chain *chain, FLAC__bool use_padding) 1120c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1121c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t current_length = chain_calculate_length_(chain); 1122c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1123c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(use_padding) { 1124c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if the metadata shrank and the last block is padding, we just extend the last padding block */ 1125c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { 1126c74663799493f2b1e6123c18def94295d0afab7Kenny Root const off_t delta = chain->initial_length - current_length; 1127c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->tail->data->length += delta; 1128c74663799493f2b1e6123c18def94295d0afab7Kenny Root current_length += delta; 1129c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(current_length == chain->initial_length); 1130c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1131c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if the metadata shrank more than 4 bytes then there's room to add another padding block */ 1132c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) { 1133c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata *padding; 1134c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node; 1135c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) { 1136c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1137c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0; 1138c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1139c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding->length = chain->initial_length - (FLAC__STREAM_METADATA_HEADER_LENGTH + current_length); 1140c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (node = node_new_())) { 1141c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(padding); 1142c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1143c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0; 1144c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1145c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data = padding; 1146c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_append_node_(chain, node); 1147c74663799493f2b1e6123c18def94295d0afab7Kenny Root current_length = chain_calculate_length_(chain); 1148c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(current_length == chain->initial_length); 1149c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1150c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */ 1151c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(current_length > chain->initial_length) { 1152c74663799493f2b1e6123c18def94295d0afab7Kenny Root const off_t delta = current_length - chain->initial_length; 1153c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { 1154c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if the delta is exactly the size of the last padding block, remove the padding block */ 1155c74663799493f2b1e6123c18def94295d0afab7Kenny Root if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) { 1156c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_delete_node_(chain, chain->tail); 1157c74663799493f2b1e6123c18def94295d0afab7Kenny Root current_length = chain_calculate_length_(chain); 1158c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(current_length == chain->initial_length); 1159c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1160c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if there is at least 'delta' bytes of padding, trim the padding down */ 1161c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if((off_t)chain->tail->data->length >= delta) { 1162c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->tail->data->length -= delta; 1163c74663799493f2b1e6123c18def94295d0afab7Kenny Root current_length -= delta; 1164c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(current_length == chain->initial_length); 1165c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1166c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1167c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1168c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1169c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1170c74663799493f2b1e6123c18def94295d0afab7Kenny Root return current_length; 1171c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1172c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1173c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic 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) 1174c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1175c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node; 1176c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1177c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1178c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1179c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* we assume we're already at the beginning of the file */ 1180c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1181c74663799493f2b1e6123c18def94295d0afab7Kenny Root switch(seek_to_first_metadata_block_cb_(handle, read_cb, seek_cb)) { 1182c74663799493f2b1e6123c18def94295d0afab7Kenny Root case 0: 1183c74663799493f2b1e6123c18def94295d0afab7Kenny Root break; 1184c74663799493f2b1e6123c18def94295d0afab7Kenny Root case 1: 1185c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1186c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1187c74663799493f2b1e6123c18def94295d0afab7Kenny Root case 2: 1188c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1189c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1190c74663799493f2b1e6123c18def94295d0afab7Kenny Root case 3: 1191c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE; 1192c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1193c74663799493f2b1e6123c18def94295d0afab7Kenny Root default: 1194c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0); 1195c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1196c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1197c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1198c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 1199c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__int64 pos = tell_cb(handle); 1200c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(pos < 0) { 1201c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1202c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1203c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1204c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->first_offset = (off_t)pos; 1205c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1206c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1207c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 1208c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool is_last; 1209c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__MetadataType type; 1210c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned length; 1211c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1212c74663799493f2b1e6123c18def94295d0afab7Kenny Root do { 1213c74663799493f2b1e6123c18def94295d0afab7Kenny Root node = node_new_(); 1214c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == node) { 1215c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1216c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1217c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1218c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1219c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!read_metadata_block_header_cb_(handle, read_cb, &is_last, &type, &length)) { 1220ffb50496c70cd15e456bc1a37a4b3d62fc0db6c5Patrick Jacques node_delete_(node); 1221c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1222c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1223c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1224c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1225c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data = FLAC__metadata_object_new(type); 1226c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == node->data) { 1227c74663799493f2b1e6123c18def94295d0afab7Kenny Root node_delete_(node); 1228c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1229c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1230c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1231c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1232c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data->is_last = is_last; 1233c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data->length = length; 1234c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1235c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = get_equivalent_status_(read_metadata_block_data_cb_(handle, read_cb, seek_cb, node->data)); 1236c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { 1237c74663799493f2b1e6123c18def94295d0afab7Kenny Root node_delete_(node); 1238c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1239c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1240c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_append_node_(chain, node); 1241c74663799493f2b1e6123c18def94295d0afab7Kenny Root } while(!is_last); 1242c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1243c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1244c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 1245c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__int64 pos = tell_cb(handle); 1246c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(pos < 0) { 1247c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 1248c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1249c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1250c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->last_offset = (off_t)pos; 1251c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1252c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1253c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->initial_length = chain_calculate_length_(chain); 1254c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1255c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1256c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1257c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1258c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__StreamDecoderReadStatus chain_read_ogg_read_cb_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) 1259c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1260c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1261c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)decoder; 1262c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(*bytes > 0 && chain->status == FLAC__METADATA_CHAIN_STATUS_OK) { 1263c74663799493f2b1e6123c18def94295d0afab7Kenny Root *bytes = chain->read_cb(buffer, sizeof(FLAC__byte), *bytes, chain->handle); 1264c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(*bytes == 0) 1265c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; 1266c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 1267c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; 1268c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1269c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 1270c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__STREAM_DECODER_READ_STATUS_ABORT; 1271c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1272c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1273c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__StreamDecoderWriteStatus chain_read_ogg_write_cb_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) 1274c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1275c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)decoder, (void)frame, (void)buffer, (void)client_data; 1276c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; 1277c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1278c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1279c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void chain_read_ogg_metadata_cb_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) 1280c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1281c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1282c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node; 1283c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1284c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)decoder; 1285c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1286c74663799493f2b1e6123c18def94295d0afab7Kenny Root node = node_new_(); 1287c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == node) { 1288c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1289c74663799493f2b1e6123c18def94295d0afab7Kenny Root return; 1290c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1291c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1292c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data = FLAC__metadata_object_clone(metadata); 1293c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == node->data) { 1294c74663799493f2b1e6123c18def94295d0afab7Kenny Root node_delete_(node); 1295c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1296c74663799493f2b1e6123c18def94295d0afab7Kenny Root return; 1297c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1298c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1299c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_append_node_(chain, node); 1300c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1301c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1302c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic void chain_read_ogg_error_cb_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) 1303c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1304c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; 1305c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)decoder, (void)status; 1306c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1307c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1308c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1309c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool chain_read_ogg_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb) 1310c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1311c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamDecoder *decoder; 1312c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1313c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1314c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1315c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* we assume we're already at the beginning of the file */ 1316c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1317c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->handle = handle; 1318c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->read_cb = read_cb; 1319c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (decoder = FLAC__stream_decoder_new())) { 1320c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1321c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1322c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1323c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_set_metadata_respond_all(decoder); 1324c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(FLAC__stream_decoder_init_ogg_stream(decoder, chain_read_ogg_read_cb_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, chain_read_ogg_write_cb_, chain_read_ogg_metadata_cb_, chain_read_ogg_error_cb_, chain) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { 1325c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_delete(decoder); 1326c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1327c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1328c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1329c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1330c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->first_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */ 1331c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1332c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) 1333c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ 1334c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { 1335c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_delete(decoder); 1336c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1337c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1338c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1339c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__stream_decoder_delete(decoder); 1340c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1341c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->last_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */ 1342c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1343c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->initial_length = chain_calculate_length_(chain); 1344c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1345c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1346c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1347c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1348c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool chain_rewrite_metadata_in_place_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, FLAC__IOCallback_Seek seek_cb) 1349c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1350c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node; 1351c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1352c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1353c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain->head); 1354c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1355c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != seek_cb(handle, chain->first_offset, SEEK_SET)) { 1356c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1357c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1358c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1359c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1360c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(node = chain->head; node; node = node->next) { 1361c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_header_cb_(handle, write_cb, node->data)) { 1362c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1363c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1364c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1365c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_data_cb_(handle, write_cb, node->data)) { 1366c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1367c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1368c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1369c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1370c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1371c74663799493f2b1e6123c18def94295d0afab7Kenny Root /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1372c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1373c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_OK; 1374c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1375c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1376c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1377c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool chain_rewrite_metadata_in_place_(FLAC__Metadata_Chain *chain) 1378c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1379c74663799493f2b1e6123c18def94295d0afab7Kenny Root FILE *file; 1380c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool ret; 1381c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1382c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain->filename); 1383c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1384c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (file = fopen(chain->filename, "r+b"))) { 1385c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1386c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1387c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1388c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1389c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* chain_rewrite_metadata_in_place_cb_() sets chain->status for us */ 1390c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = chain_rewrite_metadata_in_place_cb_(chain, (FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, fseek_wrapper_); 1391c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1392c74663799493f2b1e6123c18def94295d0afab7Kenny Root fclose(file); 1393c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1394c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 1395c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1396c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1397c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *tempfile_path_prefix) 1398c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1399c74663799493f2b1e6123c18def94295d0afab7Kenny Root FILE *f, *tempfile; 1400c74663799493f2b1e6123c18def94295d0afab7Kenny Root char *tempfilename; 1401c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIteratorStatus status; 1402c74663799493f2b1e6123c18def94295d0afab7Kenny Root const FLAC__Metadata_Node *node; 1403c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1404c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1405c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain->filename); 1406c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain->head); 1407c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1408c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* copy the file prefix (data up to first metadata block */ 1409c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (f = fopen(chain->filename, "rb"))) { 1410c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1411c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1412c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1413c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) { 1414c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = get_equivalent_status_(status); 1415c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(&tempfile, &tempfilename); 1416c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1417c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1418c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) { 1419c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = get_equivalent_status_(status); 1420c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(&tempfile, &tempfilename); 1421c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1422c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1423c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1424c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* write the metadata */ 1425c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(node = chain->head; node; node = node->next) { 1426c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_header_(tempfile, &status, node->data)) { 1427c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = get_equivalent_status_(status); 1428c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1429c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1430c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_data_(tempfile, &status, node->data)) { 1431c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = get_equivalent_status_(status); 1432c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1433c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1434c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1435c74663799493f2b1e6123c18def94295d0afab7Kenny Root /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1436c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1437c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* copy the file postfix (everything after the metadata) */ 1438c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(f, chain->last_offset, SEEK_SET)) { 1439c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(&tempfile, &tempfilename); 1440c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1441c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1442c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1443c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) { 1444c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(&tempfile, &tempfilename); 1445c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = get_equivalent_status_(status); 1446c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1447c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1448c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1449c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* move the tempfile on top of the original */ 1450c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)fclose(f); 1451c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status)) 1452c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1453c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1454c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1455c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1456c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1457c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* assumes 'handle' is already at beginning of file */ 1458c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool chain_rewrite_file_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb) 1459c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1460c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIteratorStatus status; 1461c74663799493f2b1e6123c18def94295d0afab7Kenny Root const FLAC__Metadata_Node *node; 1462c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1463c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1464c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == chain->filename); 1465c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain->head); 1466c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1467c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* copy the file prefix (data up to first metadata block */ 1468c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!copy_n_bytes_from_file_cb_(handle, read_cb, temp_handle, temp_write_cb, chain->first_offset, &status)) { 1469c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = get_equivalent_status_(status); 1470c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1471c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1472c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1473c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* write the metadata */ 1474c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(node = chain->head; node; node = node->next) { 1475c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_header_cb_(temp_handle, temp_write_cb, node->data)) { 1476c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1477c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1478c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1479c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_data_cb_(temp_handle, temp_write_cb, node->data)) { 1480c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 1481c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1482c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1483c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1484c74663799493f2b1e6123c18def94295d0afab7Kenny Root /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ 1485c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1486c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* copy the file postfix (everything after the metadata) */ 1487c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != seek_cb(handle, chain->last_offset, SEEK_SET)) { 1488c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1489c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1490c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1491c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!copy_remaining_bytes_from_file_cb_(handle, read_cb, eof_cb, temp_handle, temp_write_cb, &status)) { 1492c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = get_equivalent_status_(status); 1493c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1494c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1495c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1496c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1497c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1498c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1499c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void) 1500c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1501c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)calloc(1, sizeof(FLAC__Metadata_Chain)); 1502c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1503c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != chain) 1504c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_init_(chain); 1505c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1506c74663799493f2b1e6123c18def94295d0afab7Kenny Root return chain; 1507c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1508c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1509c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain) 1510c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1511c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1512c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1513c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_clear_(chain); 1514c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1515c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(chain); 1516c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1517c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1518c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain) 1519c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1520c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_ChainStatus status; 1521c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1522c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1523c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1524c74663799493f2b1e6123c18def94295d0afab7Kenny Root status = chain->status; 1525c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_OK; 1526c74663799493f2b1e6123c18def94295d0afab7Kenny Root return status; 1527c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1528c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1529c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool chain_read_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool is_ogg) 1530c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1531c74663799493f2b1e6123c18def94295d0afab7Kenny Root FILE *file; 1532c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool ret; 1533c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1534c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1535c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 1536c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1537c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_clear_(chain); 1538c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1539c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (chain->filename = strdup(filename))) { 1540c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 1541c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1542c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1543c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1544c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->is_ogg = is_ogg; 1545c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1546c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (file = fopen(filename, "rb"))) { 1547c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 1548c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1549c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1550c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1551c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* the function also sets chain->status for us */ 1552c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = is_ogg? 1553c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_read_ogg_cb_(chain, file, (FLAC__IOCallback_Read)fread) : 1554c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_) 1555c74663799493f2b1e6123c18def94295d0afab7Kenny Root ; 1556c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1557c74663799493f2b1e6123c18def94295d0afab7Kenny Root fclose(file); 1558c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1559c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 1560c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1561c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1562c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename) 1563c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1564c74663799493f2b1e6123c18def94295d0afab7Kenny Root return chain_read_(chain, filename, /*is_ogg=*/false); 1565c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1566c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1567c74663799493f2b1e6123c18def94295d0afab7Kenny Root/*@@@@add to tests*/ 1568c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename) 1569c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1570c74663799493f2b1e6123c18def94295d0afab7Kenny Root return chain_read_(chain, filename, /*is_ogg=*/true); 1571c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1572c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1573c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__bool chain_read_with_callbacks_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__bool is_ogg) 1574c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1575c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__bool ret; 1576c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1577c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1578c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1579c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_clear_(chain); 1580c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1581c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) { 1582c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1583c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1584c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1585c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1586c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->is_ogg = is_ogg; 1587c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1588c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* rewind */ 1589c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != callbacks.seek(handle, 0, SEEK_SET)) { 1590c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1591c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1592c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1593c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1594c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* the function also sets chain->status for us */ 1595c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = is_ogg? 1596c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_read_ogg_cb_(chain, handle, callbacks.read) : 1597c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell) 1598c74663799493f2b1e6123c18def94295d0afab7Kenny Root ; 1599c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1600c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 1601c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1602c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1603c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1604c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1605c74663799493f2b1e6123c18def94295d0afab7Kenny Root return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/false); 1606c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1607c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1608c74663799493f2b1e6123c18def94295d0afab7Kenny Root/*@@@@add to tests*/ 1609c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1610c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1611c74663799493f2b1e6123c18def94295d0afab7Kenny Root return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/true); 1612c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1613c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1614c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding) 1615c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1616c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* This does all the same checks that are in chain_prepare_for_write_() 1617c74663799493f2b1e6123c18def94295d0afab7Kenny Root * but doesn't actually alter the chain. Make sure to update the logic 1618c74663799493f2b1e6123c18def94295d0afab7Kenny Root * here if chain_prepare_for_write_() changes. 1619c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 1620c74663799493f2b1e6123c18def94295d0afab7Kenny Root const off_t current_length = chain_calculate_length_(chain); 1621c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1622c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1623c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1624c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(use_padding) { 1625c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if the metadata shrank and the last block is padding, we just extend the last padding block */ 1626c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) 1627c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1628c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if the metadata shrank more than 4 bytes then there's room to add another padding block */ 1629c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) 1630c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1631c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */ 1632c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(current_length > chain->initial_length) { 1633c74663799493f2b1e6123c18def94295d0afab7Kenny Root const off_t delta = current_length - chain->initial_length; 1634c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { 1635c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if the delta is exactly the size of the last padding block, remove the padding block */ 1636c74663799493f2b1e6123c18def94295d0afab7Kenny Root if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) 1637c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1638c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* if there is at least 'delta' bytes of padding, trim the padding down */ 1639c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if((off_t)chain->tail->data->length >= delta) 1640c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1641c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1642c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1643c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1644c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1645c74663799493f2b1e6123c18def94295d0afab7Kenny Root return (current_length != chain->initial_length); 1646c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1647c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1648c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats) 1649c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1650c74663799493f2b1e6123c18def94295d0afab7Kenny Root struct stat stats; 1651c74663799493f2b1e6123c18def94295d0afab7Kenny Root const char *tempfile_path_prefix = 0; 1652c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t current_length; 1653c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1654c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1655c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1656c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1657c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1658c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1659c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1660c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1661c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 == chain->filename) { 1662c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1663c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1664c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1665c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1666c74663799493f2b1e6123c18def94295d0afab7Kenny Root current_length = chain_prepare_for_write_(chain, use_padding); 1667c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1668c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* a return value of 0 means there was an error; chain->status is already set */ 1669c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 == current_length) 1670c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1671c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1672c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(preserve_file_stats) 1673c74663799493f2b1e6123c18def94295d0afab7Kenny Root get_file_stats_(chain->filename, &stats); 1674c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1675c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(current_length == chain->initial_length) { 1676c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!chain_rewrite_metadata_in_place_(chain)) 1677c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1678c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1679c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 1680c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!chain_rewrite_file_(chain, tempfile_path_prefix)) 1681c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1682c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1683c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* recompute lengths and offsets */ 1684c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 1685c74663799493f2b1e6123c18def94295d0afab7Kenny Root const FLAC__Metadata_Node *node; 1686c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->initial_length = current_length; 1687c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->last_offset = chain->first_offset; 1688c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(node = chain->head; node; node = node->next) 1689c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); 1690c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1691c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1692c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1693c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(preserve_file_stats) 1694c74663799493f2b1e6123c18def94295d0afab7Kenny Root set_file_stats_(chain->filename, &stats); 1695c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1696c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1697c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1698c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1699c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) 1700c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1701c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t current_length; 1702c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1703c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1704c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1705c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1706c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1707c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1708c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1709c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1710c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 != chain->filename) { 1711c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1712c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1713c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1714c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1715c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 == callbacks.write || 0 == callbacks.seek) { 1716c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1717c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1718c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1719c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1720c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { 1721c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; 1722c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1723c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1724c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1725c74663799493f2b1e6123c18def94295d0afab7Kenny Root current_length = chain_prepare_for_write_(chain, use_padding); 1726c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1727c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* a return value of 0 means there was an error; chain->status is already set */ 1728c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 == current_length) 1729c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1730c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1731c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(current_length == chain->initial_length); 1732c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1733c74663799493f2b1e6123c18def94295d0afab7Kenny Root return chain_rewrite_metadata_in_place_cb_(chain, handle, callbacks.write, callbacks.seek); 1734c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1735c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1736c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks) 1737c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1738c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t current_length; 1739c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1740c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1741c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1742c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ 1743c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 1744c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1745c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1746c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1747c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 != chain->filename) { 1748c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; 1749c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1750c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1751c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1752c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.eof) { 1753c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1754c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1755c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1756c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 == temp_callbacks.write) { 1757c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; 1758c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1759c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1760c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1761c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (!FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { 1762c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; 1763c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1764c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1765c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1766c74663799493f2b1e6123c18def94295d0afab7Kenny Root current_length = chain_prepare_for_write_(chain, use_padding); 1767c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1768c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* a return value of 0 means there was an error; chain->status is already set */ 1769c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (0 == current_length) 1770c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1771c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1772c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(current_length != chain->initial_length); 1773c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1774c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* rewind */ 1775c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != callbacks.seek(handle, 0, SEEK_SET)) { 1776c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 1777c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1778c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1779c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1780c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!chain_rewrite_file_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.eof, temp_handle, temp_callbacks.write)) 1781c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1782c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1783c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* recompute lengths and offsets */ 1784c74663799493f2b1e6123c18def94295d0afab7Kenny Root { 1785c74663799493f2b1e6123c18def94295d0afab7Kenny Root const FLAC__Metadata_Node *node; 1786c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->initial_length = current_length; 1787c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->last_offset = chain->first_offset; 1788c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(node = chain->head; node; node = node->next) 1789c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); 1790c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1791c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1792c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1793c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1794c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1795c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain) 1796c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1797c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node; 1798c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1799c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1800c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1801c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(node = chain->head; node; ) { 1802c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!chain_merge_adjacent_padding_(chain, node)) 1803c74663799493f2b1e6123c18def94295d0afab7Kenny Root node = node->next; 1804c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1805c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1806c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1807c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain) 1808c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1809c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node, *save; 1810c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 1811c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1812c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1813c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1814c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* 1815c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Don't try and be too smart... this simple algo is good enough for 1816c74663799493f2b1e6123c18def94295d0afab7Kenny Root * the small number of nodes that we deal with. 1817c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 1818c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0, node = chain->head; i < chain->nodes; i++) { 1819c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(node->data->type == FLAC__METADATA_TYPE_PADDING) { 1820c74663799493f2b1e6123c18def94295d0afab7Kenny Root save = node->next; 1821c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_remove_node_(chain, node); 1822c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_append_node_(chain, node); 1823c74663799493f2b1e6123c18def94295d0afab7Kenny Root node = save; 1824c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1825c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 1826c74663799493f2b1e6123c18def94295d0afab7Kenny Root node = node->next; 1827c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1828c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1829c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1830c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_chain_merge_padding(chain); 1831c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1832c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1833c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1834c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void) 1835c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1836c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Iterator *iterator = (FLAC__Metadata_Iterator*)calloc(1, sizeof(FLAC__Metadata_Iterator)); 1837c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1838c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* calloc() implies: 1839c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current = 0; 1840c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->chain = 0; 1841c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 1842c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1843c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator; 1844c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1845c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1846c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator) 1847c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1848c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1849c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1850c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(iterator); 1851c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1852c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1853c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain) 1854c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1855c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1856c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain); 1857c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != chain->head); 1858c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1859c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->chain = chain; 1860c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current = chain->head; 1861c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1862c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1863c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator) 1864c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1865c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1866c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1867c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == iterator->current || 0 == iterator->current->next) 1868c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1869c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1870c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current = iterator->current->next; 1871c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1872c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1873c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1874c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator) 1875c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1876c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1877c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1878c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == iterator->current || 0 == iterator->current->prev) 1879c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1880c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1881c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current = iterator->current->prev; 1882c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1883c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1884c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1885c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator) 1886c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1887c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1888c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->current); 1889c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->current->data); 1890c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1891c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator->current->data->type; 1892c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1893c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1894c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator) 1895c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1896c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1897c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->current); 1898c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1899c74663799493f2b1e6123c18def94295d0afab7Kenny Root return iterator->current->data; 1900c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1901c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1902c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1903c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1904c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1905c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != block); 1906c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block); 1907c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1908c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1909c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding) 1910c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1911c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *save; 1912c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1913c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1914c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->current); 1915c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1916c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == iterator->current->prev) { 1917c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); 1918c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1919c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1920c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1921c74663799493f2b1e6123c18def94295d0afab7Kenny Root save = iterator->current->prev; 1922c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1923c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(replace_with_padding) { 1924c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete_data(iterator->current->data); 1925c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current->data->type = FLAC__METADATA_TYPE_PADDING; 1926c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1927c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 1928c74663799493f2b1e6123c18def94295d0afab7Kenny Root chain_delete_node_(iterator->chain, iterator->current); 1929c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1930c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1931c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current = save; 1932c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1933c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1934c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1935c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1936c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1937c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node; 1938c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1939c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1940c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->current); 1941c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != block); 1942c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1943c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block->type == FLAC__METADATA_TYPE_STREAMINFO) 1944c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1945c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1946c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == iterator->current->prev) { 1947c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); 1948c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1949c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1950c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1951c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (node = node_new_())) 1952c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1953c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1954c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data = block; 1955c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator_insert_node_(iterator, node); 1956c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current = node; 1957c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1958c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1959c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1960c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) 1961c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1962c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_Node *node; 1963c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1964c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 1965c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->current); 1966c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != block); 1967c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1968c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block->type == FLAC__METADATA_TYPE_STREAMINFO) 1969c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1970c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1971c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (node = node_new_())) 1972c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 1973c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1974c74663799493f2b1e6123c18def94295d0afab7Kenny Root node->data = block; 1975c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator_insert_node_after_(iterator, node); 1976c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->current = node; 1977c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 1978c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1979c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1980c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1981c74663799493f2b1e6123c18def94295d0afab7Kenny Root/**************************************************************************** 1982c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 1983c74663799493f2b1e6123c18def94295d0afab7Kenny Root * Local function definitions 1984c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 1985c74663799493f2b1e6123c18def94295d0afab7Kenny Root ***************************************************************************/ 1986c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1987c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes) 1988c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 1989c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 1990c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1991c74663799493f2b1e6123c18def94295d0afab7Kenny Root b += bytes; 1992c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1993c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < bytes; i++) { 1994c74663799493f2b1e6123c18def94295d0afab7Kenny Root *(--b) = (FLAC__byte)(val & 0xff); 1995c74663799493f2b1e6123c18def94295d0afab7Kenny Root val >>= 8; 1996c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 1997c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 1998c74663799493f2b1e6123c18def94295d0afab7Kenny Root 1999c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes) 2000c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2001c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2002c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2003c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < bytes; i++) { 2004c74663799493f2b1e6123c18def94295d0afab7Kenny Root *(b++) = (FLAC__byte)(val & 0xff); 2005c74663799493f2b1e6123c18def94295d0afab7Kenny Root val >>= 8; 2006c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2007c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2008c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2009c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes) 2010c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2011c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2012c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2013c74663799493f2b1e6123c18def94295d0afab7Kenny Root b += bytes; 2014c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2015c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < bytes; i++) { 2016c74663799493f2b1e6123c18def94295d0afab7Kenny Root *(--b) = (FLAC__byte)(val & 0xff); 2017c74663799493f2b1e6123c18def94295d0afab7Kenny Root val >>= 8; 2018c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2019c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2020c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2021c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes) 2022c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2023c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__uint32 ret = 0; 2024c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2025c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2026c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < bytes; i++) 2027c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = (ret << 8) | (FLAC__uint32)(*b++); 2028c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2029c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 2030c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2031c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2032c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes) 2033c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2034c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__uint32 ret = 0; 2035c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2036c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2037c74663799493f2b1e6123c18def94295d0afab7Kenny Root b += bytes; 2038c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2039c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < bytes; i++) 2040c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = (ret << 8) | (FLAC__uint32)(*--b); 2041c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2042c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 2043c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2044c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2045c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes) 2046c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2047c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__uint64 ret = 0; 2048c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2049c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2050c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < bytes; i++) 2051c74663799493f2b1e6123c18def94295d0afab7Kenny Root ret = (ret << 8) | (FLAC__uint64)(*b++); 2052c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2053c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ret; 2054c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2055c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2056c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator) 2057c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2058c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 2059c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 2060c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2061c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!read_metadata_block_header_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, &iterator->is_last, &iterator->type, &iterator->length)) { 2062c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2063c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2064c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2065c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2066c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2067c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2068c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2069c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block) 2070c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2071c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator); 2072c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != iterator->file); 2073c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2074c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = read_metadata_block_data_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, block); 2075c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2076c74663799493f2b1e6123c18def94295d0afab7Kenny Root return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK); 2077c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2078c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2079c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length) 2080c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2081c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH]; 2082c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2083c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH) 2084c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2085c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2086c74663799493f2b1e6123c18def94295d0afab7Kenny Root *is_last = raw_header[0] & 0x80? true : false; 2087c74663799493f2b1e6123c18def94295d0afab7Kenny Root *type = (FLAC__MetadataType)(raw_header[0] & 0x7f); 2088c74663799493f2b1e6123c18def94295d0afab7Kenny Root *length = unpack_uint32_(raw_header + 1, 3); 2089c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2090c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* Note that we don't check: 2091c74663799493f2b1e6123c18def94295d0afab7Kenny Root * if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED) 2092c74663799493f2b1e6123c18def94295d0afab7Kenny Root * we just will read in an opaque block 2093c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 2094c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2095c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2096c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2097c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2098c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block) 2099c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2100c74663799493f2b1e6123c18def94295d0afab7Kenny Root switch(block->type) { 2101c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_STREAMINFO: 2102c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_data_streaminfo_cb_(handle, read_cb, &block->data.stream_info); 2103c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_PADDING: 2104c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_data_padding_cb_(handle, seek_cb, &block->data.padding, block->length); 2105c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_APPLICATION: 2106c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_data_application_cb_(handle, read_cb, &block->data.application, block->length); 2107c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_SEEKTABLE: 2108c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_data_seektable_cb_(handle, read_cb, &block->data.seek_table, block->length); 2109c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_VORBIS_COMMENT: 2110c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment); 2111c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_CUESHEET: 2112c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet); 2113c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_PICTURE: 2114c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_data_picture_cb_(handle, read_cb, &block->data.picture); 2115c74663799493f2b1e6123c18def94295d0afab7Kenny Root default: 2116c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length); 2117c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2118c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2119c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2120c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block) 2121c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2122c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b; 2123c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2124c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) 2125c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2126c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2127c74663799493f2b1e6123c18def94295d0afab7Kenny Root b = buffer; 2128c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2129c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* we are using hardcoded numbers for simplicity but we should 2130c74663799493f2b1e6123c18def94295d0afab7Kenny Root * probably eventually write a bit-level unpacker and use the 2131c74663799493f2b1e6123c18def94295d0afab7Kenny Root * _STREAMINFO_ constants. 2132c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 2133c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->min_blocksize = unpack_uint32_(b, 2); b += 2; 2134c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->max_blocksize = unpack_uint32_(b, 2); b += 2; 2135c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->min_framesize = unpack_uint32_(b, 3); b += 3; 2136c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->max_framesize = unpack_uint32_(b, 3); b += 3; 2137c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4); 2138c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1; 2139c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 4) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1; 2140c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4); 2141c74663799493f2b1e6123c18def94295d0afab7Kenny Root memcpy(block->md5sum, b+8, 16); 2142c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2143c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2144c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2145c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2146c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length) 2147c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2148c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)block; /* nothing to do; we don't care about reading the padding bytes */ 2149c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2150c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != seek_cb(handle, block_length, SEEK_CUR)) 2151c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2152c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2153c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2154c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2155c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2156c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length) 2157c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2158c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; 2159c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2160c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(block->id, 1, id_bytes, handle) != id_bytes) 2161c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2162c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2163c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block_length < id_bytes) 2164c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2165c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2166c74663799493f2b1e6123c18def94295d0afab7Kenny Root block_length -= id_bytes; 2167c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2168c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block_length == 0) { 2169c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->data = 0; 2170c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2171c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 2172c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (block->data = (FLAC__byte*)malloc(block_length))) 2173c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2174c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2175c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(block->data, 1, block_length, handle) != block_length) 2176c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2177c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2178c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2179c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2180c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2181c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2182c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length) 2183c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2184c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2185c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH]; 2186c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2187c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0); 2188c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2189c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; 2190c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2191c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block->num_points == 0) 2192c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->points = 0; 2193c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(0 == (block->points = (FLAC__StreamMetadata_SeekPoint*)safe_malloc_mul_2op_(block->num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) 2194c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2195c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2196c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < block->num_points; i++) { 2197c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) 2198c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2199c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* some MAGIC NUMBERs here */ 2200c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->points[i].sample_number = unpack_uint64_(buffer, 8); 2201c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->points[i].stream_offset = unpack_uint64_(buffer+8, 8); 2202c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->points[i].frame_samples = unpack_uint32_(buffer+16, 2); 2203c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2204c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2205c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2206c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2207c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2208c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry) 2209c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2210c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8; 2211c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[4]; /* magic number is asserted below */ 2212c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2213c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == sizeof(buffer)); 2214c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2215c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2216c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2217c74663799493f2b1e6123c18def94295d0afab7Kenny Root entry->length = unpack_uint32_little_endian_(buffer, entry_length_len); 2218c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2219c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != entry->entry) 2220c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(entry->entry); 2221c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2222c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(entry->length == 0) { 2223c74663799493f2b1e6123c18def94295d0afab7Kenny Root entry->entry = 0; 2224c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2225c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 2226c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (entry->entry = (FLAC__byte*)safe_malloc_add_2op_(entry->length, /*+*/1))) 2227c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2228c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2229c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(entry->entry, 1, entry->length, handle) != entry->length) 2230c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2231c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2232c74663799493f2b1e6123c18def94295d0afab7Kenny Root entry->entry[entry->length] = '\0'; 2233c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2234c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2235c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2236c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2237c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2238c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block) 2239c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2240c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2241c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIteratorStatus status; 2242c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8; 2243c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[4]; /* magic number is asserted below */ 2244c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2245c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == sizeof(buffer)); 2246c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2247c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string)))) 2248c74663799493f2b1e6123c18def94295d0afab7Kenny Root return status; 2249c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2250c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, num_comments_len, handle) != num_comments_len) 2251c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2252c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len); 2253c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2254c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block->num_comments == 0) { 2255c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->comments = 0; 2256c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2257c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(0 == (block->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) 2258c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2259c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2260c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < block->num_comments; i++) { 2261c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, block->comments + i))) 2262c74663799493f2b1e6123c18def94295d0afab7Kenny Root return status; 2263c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2264c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2265c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2266c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2267c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2268c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track) 2269c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2270c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i, len; 2271c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[32]; /* asserted below that this is big enough */ 2272c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2273c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64)); 2274c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); 2275c74663799493f2b1e6123c18def94295d0afab7Kenny Root 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); 2276c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2277c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); 2278c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; 2279c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2280c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2281c74663799493f2b1e6123c18def94295d0afab7Kenny Root track->offset = unpack_uint64_(buffer, len); 2282c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2283c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); 2284c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; 2285c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2286c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2287c74663799493f2b1e6123c18def94295d0afab7Kenny Root track->number = (FLAC__byte)unpack_uint32_(buffer, len); 2288c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2289c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); 2290c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; 2291c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(track->isrc, 1, len, handle) != len) 2292c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2293c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2294c74663799493f2b1e6123c18def94295d0afab7Kenny Root 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); 2295c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; 2296c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2297c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2298c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN == 1); 2299c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN == 1); 2300c74663799493f2b1e6123c18def94295d0afab7Kenny Root track->type = buffer[0] >> 7; 2301c74663799493f2b1e6123c18def94295d0afab7Kenny Root track->pre_emphasis = (buffer[0] >> 6) & 1; 2302c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2303c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); 2304c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; 2305c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2306c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2307c74663799493f2b1e6123c18def94295d0afab7Kenny Root track->num_indices = (FLAC__byte)unpack_uint32_(buffer, len); 2308c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2309c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(track->num_indices == 0) { 2310c74663799493f2b1e6123c18def94295d0afab7Kenny Root track->indices = 0; 2311c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2312c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) 2313c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2314c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2315c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < track->num_indices; i++) { 2316c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); 2317c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; 2318c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2319c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2320c74663799493f2b1e6123c18def94295d0afab7Kenny Root track->indices[i].offset = unpack_uint64_(buffer, len); 2321c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2322c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); 2323c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; 2324c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2325c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2326c74663799493f2b1e6123c18def94295d0afab7Kenny Root track->indices[i].number = (FLAC__byte)unpack_uint32_(buffer, len); 2327c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2328c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); 2329c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; 2330c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2331c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2332c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2333c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2334c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2335c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2336c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2337c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block) 2338c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2339c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i, len; 2340c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIteratorStatus status; 2341c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[1024]; /* MSVC needs a constant expression so we put a magic number and assert */ 2342c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2343c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN)/8 <= sizeof(buffer)); 2344c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(FLAC__uint64) <= sizeof(buffer)); 2345c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2346c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); 2347c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; 2348c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(block->media_catalog_number, 1, len, handle) != len) 2349c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2350c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2351c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); 2352c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; 2353c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2354c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2355c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->lead_in = unpack_uint64_(buffer, len); 2356c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2357c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); 2358c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; 2359c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2360c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2361c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_cd = buffer[0]&0x80? true : false; 2362c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2363c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); 2364c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; 2365c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2366c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2367c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->num_tracks = unpack_uint32_(buffer, len); 2368c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2369c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block->num_tracks == 0) { 2370c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->tracks = 0; 2371c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2372c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(0 == (block->tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc(block->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) 2373c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2374c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2375c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < block->num_tracks; i++) { 2376c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_cuesheet_track_cb_(handle, read_cb, block->tracks + i))) 2377c74663799493f2b1e6123c18def94295d0afab7Kenny Root return status; 2378c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2379c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2380c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2381c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2382c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2383c74663799493f2b1e6123c18def94295d0afab7Kenny Rootstatic FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cstring_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__byte **data, FLAC__uint32 *length, FLAC__uint32 length_len) 2384c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2385c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[sizeof(FLAC__uint32)]; 2386c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2387c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != data); 2388c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(length_len%8 == 0); 2389c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2390c74663799493f2b1e6123c18def94295d0afab7Kenny Root length_len /= 8; /* convert to bytes */ 2391c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2392c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= length_len); 2393c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2394c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, length_len, handle) != length_len) 2395c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2396c74663799493f2b1e6123c18def94295d0afab7Kenny Root *length = unpack_uint32_(buffer, length_len); 2397c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2398c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != *data) 2399c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(*data); 2400c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2401c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (*data = (FLAC__byte*)safe_malloc_add_2op_(*length, /*+*/1))) 2402c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2403c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2404c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(*length > 0) { 2405c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(*data, 1, *length, handle) != *length) 2406c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2407c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2408c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2409c74663799493f2b1e6123c18def94295d0afab7Kenny Root (*data)[*length] = '\0'; 2410c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2411c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2412c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2413c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2414c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block) 2415c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2416c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__Metadata_SimpleIteratorStatus status; 2417c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[4]; /* asserted below that this is big enough */ 2418c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__uint32 len; 2419c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2420c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8); 2421c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8); 2422c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8); 2423c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8); 2424c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8); 2425c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2426c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_TYPE_LEN % 8 == 0); 2427c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN / 8; 2428c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2429c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2430c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->type = (FLAC__StreamMetadata_Picture_Type)unpack_uint32_(buffer, len); 2431c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2432c74663799493f2b1e6123c18def94295d0afab7Kenny Root if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, (FLAC__byte**)(&(block->mime_type)), &len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) 2433c74663799493f2b1e6123c18def94295d0afab7Kenny Root return status; 2434c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2435c74663799493f2b1e6123c18def94295d0afab7Kenny Root if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->description), &len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) 2436c74663799493f2b1e6123c18def94295d0afab7Kenny Root return status; 2437c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2438c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN % 8 == 0); 2439c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN / 8; 2440c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2441c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2442c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->width = unpack_uint32_(buffer, len); 2443c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2444c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN % 8 == 0); 2445c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN / 8; 2446c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2447c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2448c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->height = unpack_uint32_(buffer, len); 2449c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2450c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN % 8 == 0); 2451c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN / 8; 2452c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2453c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2454c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->depth = unpack_uint32_(buffer, len); 2455c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2456c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_COLORS_LEN % 8 == 0); 2457c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN / 8; 2458c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, len, handle) != len) 2459c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2460c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->colors = unpack_uint32_(buffer, len); 2461c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2462c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* for convenience we use read_metadata_block_data_picture_cstring_cb_() even though it adds an extra terminating NUL we don't use */ 2463c74663799493f2b1e6123c18def94295d0afab7Kenny Root if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->data), &(block->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) 2464c74663799493f2b1e6123c18def94295d0afab7Kenny Root return status; 2465c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2466c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2467c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2468c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2469c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length) 2470c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2471c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block_length == 0) { 2472c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->data = 0; 2473c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2474c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 2475c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (block->data = (FLAC__byte*)malloc(block_length))) 2476c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2477c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2478c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(block->data, 1, block_length, handle) != block_length) 2479c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 2480c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2481c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2482c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2483c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2484c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2485c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block) 2486c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2487c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != file); 2488c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != status); 2489c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2490c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_header_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) { 2491c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 2492c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2493c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2494c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2495c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2496c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2497c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2498c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block) 2499c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2500c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != file); 2501c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != status); 2502c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2503c74663799493f2b1e6123c18def94295d0afab7Kenny Root if (write_metadata_block_data_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) { 2504c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; 2505c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2506c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2507c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 2508c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 2509c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2510c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2511c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2512c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2513c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block) 2514c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2515c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH]; 2516c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2517c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN)); 2518c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2519c74663799493f2b1e6123c18def94295d0afab7Kenny Root buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type; 2520c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->length, buffer + 1, 3); 2521c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2522c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH) 2523c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2524c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2525c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2526c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2527c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2528c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block) 2529c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2530c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != block); 2531c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2532c74663799493f2b1e6123c18def94295d0afab7Kenny Root switch(block->type) { 2533c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_STREAMINFO: 2534c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_data_streaminfo_cb_(handle, write_cb, &block->data.stream_info); 2535c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_PADDING: 2536c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_data_padding_cb_(handle, write_cb, &block->data.padding, block->length); 2537c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_APPLICATION: 2538c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_data_application_cb_(handle, write_cb, &block->data.application, block->length); 2539c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_SEEKTABLE: 2540c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_data_seektable_cb_(handle, write_cb, &block->data.seek_table); 2541c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_VORBIS_COMMENT: 2542c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_data_vorbis_comment_cb_(handle, write_cb, &block->data.vorbis_comment); 2543c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_CUESHEET: 2544c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_data_cuesheet_cb_(handle, write_cb, &block->data.cue_sheet); 2545c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_TYPE_PICTURE: 2546c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_data_picture_cb_(handle, write_cb, &block->data.picture); 2547c74663799493f2b1e6123c18def94295d0afab7Kenny Root default: 2548c74663799493f2b1e6123c18def94295d0afab7Kenny Root return write_metadata_block_data_unknown_cb_(handle, write_cb, &block->data.unknown, block->length); 2549c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2550c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2551c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2552c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block) 2553c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2554c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH]; 2555c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned channels1 = block->channels - 1; 2556c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned bps1 = block->bits_per_sample - 1; 2557c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2558c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* we are using hardcoded numbers for simplicity but we should 2559c74663799493f2b1e6123c18def94295d0afab7Kenny Root * probably eventually write a bit-level packer and use the 2560c74663799493f2b1e6123c18def94295d0afab7Kenny Root * _STREAMINFO_ constants. 2561c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 2562c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->min_blocksize, buffer, 2); 2563c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->max_blocksize, buffer+2, 2); 2564c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->min_framesize, buffer+4, 3); 2565c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->max_framesize, buffer+7, 3); 2566c74663799493f2b1e6123c18def94295d0afab7Kenny Root buffer[10] = (block->sample_rate >> 12) & 0xff; 2567c74663799493f2b1e6123c18def94295d0afab7Kenny Root buffer[11] = (block->sample_rate >> 4) & 0xff; 2568c74663799493f2b1e6123c18def94295d0afab7Kenny Root buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4); 2569c74663799493f2b1e6123c18def94295d0afab7Kenny Root buffer[13] = (FLAC__byte)(((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f)); 2570c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4); 2571c74663799493f2b1e6123c18def94295d0afab7Kenny Root memcpy(buffer+18, block->md5sum, 16); 2572c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2573c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) 2574c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2575c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2576c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2577c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2578c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2579c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length) 2580c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2581c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i, n = block_length; 2582c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[1024]; 2583c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2584c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)block; 2585c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2586c74663799493f2b1e6123c18def94295d0afab7Kenny Root memset(buffer, 0, 1024); 2587c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2588c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < n/1024; i++) 2589c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, 1024, handle) != 1024) 2590c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2591c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2592c74663799493f2b1e6123c18def94295d0afab7Kenny Root n %= 1024; 2593c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2594c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, n, handle) != n) 2595c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2596c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2597c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2598c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2599c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2600c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length) 2601c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2602c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; 2603c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2604c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->id, 1, id_bytes, handle) != id_bytes) 2605c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2606c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2607c74663799493f2b1e6123c18def94295d0afab7Kenny Root block_length -= id_bytes; 2608c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2609c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->data, 1, block_length, handle) != block_length) 2610c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2611c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2612c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2613c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2614c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2615c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block) 2616c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2617c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2618c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH]; 2619c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2620c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < block->num_points; i++) { 2621c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* some MAGIC NUMBERs here */ 2622c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint64_(block->points[i].sample_number, buffer, 8); 2623c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint64_(block->points[i].stream_offset, buffer+8, 8); 2624c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->points[i].frame_samples, buffer+16, 2); 2625c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) 2626c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2627c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2628c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2629c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2630c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2631c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2632c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block) 2633c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2634c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2635c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8; 2636c74663799493f2b1e6123c18def94295d0afab7Kenny Root const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8; 2637c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[4]; /* magic number is asserted below */ 2638c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2639c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == sizeof(buffer)); 2640c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2641c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len); 2642c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2643c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2644c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->vendor_string.entry, 1, block->vendor_string.length, handle) != block->vendor_string.length) 2645c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2646c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2647c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len); 2648c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, num_comments_len, handle) != num_comments_len) 2649c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2650c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2651c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < block->num_comments; i++) { 2652c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len); 2653c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len) 2654c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2655c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->comments[i].entry, 1, block->comments[i].length, handle) != block->comments[i].length) 2656c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2657c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2658c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2659c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2660c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2661c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2662c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block) 2663c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2664c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i, j, len; 2665c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[1024]; /* asserted below that this is big enough */ 2666c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2667c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64)); 2668c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN/8); 2669c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN)/8); 2670c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); 2671c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2672c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); 2673c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; 2674c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->media_catalog_number, 1, len, handle) != len) 2675c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2676c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2677c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); 2678c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; 2679c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint64_(block->lead_in, buffer, len); 2680c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2681c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2682c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2683c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); 2684c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; 2685c74663799493f2b1e6123c18def94295d0afab7Kenny Root memset(buffer, 0, len); 2686c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(block->is_cd) 2687c74663799493f2b1e6123c18def94295d0afab7Kenny Root buffer[0] |= 0x80; 2688c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2689c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2690c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2691c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); 2692c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; 2693c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->num_tracks, buffer, len); 2694c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2695c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2696c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2697c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < block->num_tracks; i++) { 2698c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata_CueSheet_Track *track = block->tracks + i; 2699c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2700c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); 2701c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; 2702c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint64_(track->offset, buffer, len); 2703c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2704c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2705c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2706c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); 2707c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; 2708c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(track->number, buffer, len); 2709c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2710c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2711c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2712c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); 2713c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; 2714c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(track->isrc, 1, len, handle) != len) 2715c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2716c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2717c74663799493f2b1e6123c18def94295d0afab7Kenny Root 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); 2718c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; 2719c74663799493f2b1e6123c18def94295d0afab7Kenny Root memset(buffer, 0, len); 2720c74663799493f2b1e6123c18def94295d0afab7Kenny Root buffer[0] = (track->type << 7) | (track->pre_emphasis << 6); 2721c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2722c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2723c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2724c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); 2725c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; 2726c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(track->num_indices, buffer, len); 2727c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2728c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2729c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2730c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(j = 0; j < track->num_indices; j++) { 2731c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata_CueSheet_Index *index = track->indices + j; 2732c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2733c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); 2734c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; 2735c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint64_(index->offset, buffer, len); 2736c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2737c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2738c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2739c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); 2740c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; 2741c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(index->number, buffer, len); 2742c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2743c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2744c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2745c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); 2746c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; 2747c74663799493f2b1e6123c18def94295d0afab7Kenny Root memset(buffer, 0, len); 2748c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2749c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2750c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2751c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2752c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2753c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2754c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2755c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2756c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block) 2757c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2758c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned len; 2759c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t slen; 2760c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[4]; /* magic number is asserted below */ 2761c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2762c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_TYPE_LEN%8); 2763c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN%8); 2764c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN%8); 2765c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN%8); 2766c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN%8); 2767c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN%8); 2768c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_COLORS_LEN%8); 2769c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN%8); 2770c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8); 2771c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8); 2772c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8); 2773c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8); 2774c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8); 2775c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8); 2776c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8); 2777c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8); 2778c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2779c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8; 2780c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->type, buffer, len); 2781c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2782c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2783c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2784c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8; 2785c74663799493f2b1e6123c18def94295d0afab7Kenny Root slen = strlen(block->mime_type); 2786c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(slen, buffer, len); 2787c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2788c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2789c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->mime_type, 1, slen, handle) != slen) 2790c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2791c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2792c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8; 2793c74663799493f2b1e6123c18def94295d0afab7Kenny Root slen = strlen((const char *)block->description); 2794c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(slen, buffer, len); 2795c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2796c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2797c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->description, 1, slen, handle) != slen) 2798c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2799c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2800c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8; 2801c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->width, buffer, len); 2802c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2803c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2804c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2805c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8; 2806c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->height, buffer, len); 2807c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2808c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2809c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2810c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8; 2811c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->depth, buffer, len); 2812c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2813c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2814c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2815c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8; 2816c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->colors, buffer, len); 2817c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2818c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2819c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2820c74663799493f2b1e6123c18def94295d0afab7Kenny Root len = FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8; 2821c74663799493f2b1e6123c18def94295d0afab7Kenny Root pack_uint32_(block->data_length, buffer, len); 2822c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(buffer, 1, len, handle) != len) 2823c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2824c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->data, 1, block->data_length, handle) != block->data_length) 2825c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2826c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2827c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2828c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2829c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2830c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length) 2831c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2832c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(write_cb(block->data, 1, block_length, handle) != block_length) 2833c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2834c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2835c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2836c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2837c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2838c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block) 2839c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2840c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2841c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2842c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2843c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2844c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2845c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_header_(iterator->file, &iterator->status, block)) 2846c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2847c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2848c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_data_(iterator->file, &iterator->status, block)) 2849c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2850c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2851c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2852c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2853c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2854c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2855c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2856c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_header_(iterator); 2857c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2858c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2859c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last) 2860c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2861c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__StreamMetadata *padding; 2862c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2863c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2864c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2865c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2866c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2867c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2868c74663799493f2b1e6123c18def94295d0afab7Kenny Root block->is_last = false; 2869c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2870c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_header_(iterator->file, &iterator->status, block)) 2871c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2872c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2873c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_data_(iterator->file, &iterator->status, block)) 2874c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2875c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2876c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) 2877c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 2878c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2879c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding->is_last = padding_is_last; 2880c74663799493f2b1e6123c18def94295d0afab7Kenny Root padding->length = padding_length; 2881c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2882c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) { 2883c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(padding); 2884c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2885c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2886c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2887c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) { 2888c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(padding); 2889c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2890c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2891c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2892c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__metadata_object_delete(padding); 2893c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2894c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2895c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2896c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2897c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2898c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2899c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_header_(iterator); 2900c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2901c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2902c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append) 2903c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2904c74663799493f2b1e6123c18def94295d0afab7Kenny Root FILE *tempfile; 2905c74663799493f2b1e6123c18def94295d0afab7Kenny Root char *tempfilename; 2906c74663799493f2b1e6123c18def94295d0afab7Kenny Root int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */ 2907c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t fixup_is_last_flag_offset = -1; 2908c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2909c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != block || append == false); 2910c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2911c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->is_last) { 2912c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(append) { 2913c74663799493f2b1e6123c18def94295d0afab7Kenny Root fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */ 2914c74663799493f2b1e6123c18def94295d0afab7Kenny Root fixup_is_last_flag_offset = iterator->offset[iterator->depth]; 2915c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2916c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(0 == block) { 2917c74663799493f2b1e6123c18def94295d0afab7Kenny Root simple_iterator_push_(iterator); 2918c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__metadata_simple_iterator_prev(iterator)) { 2919c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)simple_iterator_pop_(iterator); 2920c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2921c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2922c74663799493f2b1e6123c18def94295d0afab7Kenny Root fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */ 2923c74663799493f2b1e6123c18def94295d0afab7Kenny Root fixup_is_last_flag_offset = iterator->offset[iterator->depth]; 2924c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!simple_iterator_pop_(iterator)) 2925c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2926c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2927c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2928c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2929c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append)) 2930c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2931c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2932c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != block) { 2933c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_header_(tempfile, &iterator->status, block)) { 2934c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(&tempfile, &tempfilename); 2935c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2936c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2937c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2938c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!write_metadata_block_data_(tempfile, &iterator->status, block)) { 2939c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(&tempfile, &tempfilename); 2940c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2941c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2942c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2943c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2944c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0)) 2945c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2946c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2947c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(append) 2948c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__metadata_simple_iterator_next(iterator); 2949c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2950c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 2951c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2952c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2953c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator) 2954c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2955c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH); 2956c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth]; 2957c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->depth++; 2958c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2959c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2960c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator) 2961c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2962c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->depth > 0); 2963c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->depth--; 2964c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { 2965c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 2966c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 2967c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 2968c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2969c74663799493f2b1e6123c18def94295d0afab7Kenny Root return read_metadata_block_header_(iterator); 2970c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 2971c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2972c74663799493f2b1e6123c18def94295d0afab7Kenny Root/* return meanings: 2973c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 0: ok 2974c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 1: read error 2975c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 2: seek error 2976c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 3: not a FLAC file 2977c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 2978c74663799493f2b1e6123c18def94295d0afab7Kenny Rootunsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb) 2979c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 2980c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[4]; 2981c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t n; 2982c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned i; 2983c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2984c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == sizeof(buffer)); 2985c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2986c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* skip any id3v2 tag */ 2987c74663799493f2b1e6123c18def94295d0afab7Kenny Root errno = 0; 2988c74663799493f2b1e6123c18def94295d0afab7Kenny Root n = read_cb(buffer, 1, 4, handle); 2989c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(errno) 2990c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 1; 2991c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(n != 4) 2992c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 3; 2993c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(0 == memcmp(buffer, "ID3", 3)) { 2994c74663799493f2b1e6123c18def94295d0afab7Kenny Root unsigned tag_length = 0; 2995c74663799493f2b1e6123c18def94295d0afab7Kenny Root 2996c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* skip to the tag length */ 2997c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(seek_cb(handle, 2, SEEK_CUR) < 0) 2998c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 2; 2999c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3000c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* read the length */ 3001c74663799493f2b1e6123c18def94295d0afab7Kenny Root for(i = 0; i < 4; i++) { 3002c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, 1, handle) < 1 || buffer[0] & 0x80) 3003c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 1; 3004c74663799493f2b1e6123c18def94295d0afab7Kenny Root tag_length <<= 7; 3005c74663799493f2b1e6123c18def94295d0afab7Kenny Root tag_length |= (buffer[0] & 0x7f); 3006c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3007c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3008c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* skip the rest of the tag */ 3009c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(seek_cb(handle, tag_length, SEEK_CUR) < 0) 3010c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 2; 3011c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3012c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* read the stream sync code */ 3013c74663799493f2b1e6123c18def94295d0afab7Kenny Root errno = 0; 3014c74663799493f2b1e6123c18def94295d0afab7Kenny Root n = read_cb(buffer, 1, 4, handle); 3015c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(errno) 3016c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 1; 3017c74663799493f2b1e6123c18def94295d0afab7Kenny Root else if(n != 4) 3018c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 3; 3019c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3020c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3021c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* check for the fLaC signature */ 3022c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH)) 3023c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 0; 3024c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 3025c74663799493f2b1e6123c18def94295d0afab7Kenny Root return 3; 3026c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3027c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3028c74663799493f2b1e6123c18def94295d0afab7Kenny Rootunsigned seek_to_first_metadata_block_(FILE *f) 3029c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3030c74663799493f2b1e6123c18def94295d0afab7Kenny Root return seek_to_first_metadata_block_cb_((FLAC__IOHandle)f, (FLAC__IOCallback_Read)fread, fseek_wrapper_); 3031c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3032c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3033c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append) 3034c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3035c74663799493f2b1e6123c18def94295d0afab7Kenny Root const off_t offset_end = append? iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length : iterator->offset[iterator->depth]; 3036c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3037c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, 0, SEEK_SET)) { 3038c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3039c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3040c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3041c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) { 3042c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3043c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3044c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3045c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) { 3046c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3047c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3048c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3049c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3050c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 3051c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3052c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3053c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, off_t fixup_is_last_flag_offset, FLAC__bool backup) 3054c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3055c74663799493f2b1e6123c18def94295d0afab7Kenny Root off_t save_offset = iterator->offset[iterator->depth]; 3056c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != *tempfile); 3057c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3058c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(iterator->file, save_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length, SEEK_SET)) { 3059c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3060c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3061c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3062c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3063c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) { 3064c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3065c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3066c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3067c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3068c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(fixup_is_last_code != 0) { 3069c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* 3070c74663799493f2b1e6123c18def94295d0afab7Kenny Root * if code == 1, it means a block was appended to the end so 3071c74663799493f2b1e6123c18def94295d0afab7Kenny Root * we have to clear the is_last flag of the previous block 3072c74663799493f2b1e6123c18def94295d0afab7Kenny Root * if code == -1, it means the last block was deleted so 3073c74663799493f2b1e6123c18def94295d0afab7Kenny Root * we have to set the is_last flag of the previous block 3074c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 3075c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */ 3076c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte x; 3077c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) { 3078c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3079c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3080c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3081c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3082c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(fread(&x, 1, 1, *tempfile) != 1) { 3083c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3084c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3085c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3086c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3087c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(fixup_is_last_code > 0) { 3088c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(x & 0x80); 3089c74663799493f2b1e6123c18def94295d0afab7Kenny Root x &= 0x7f; 3090c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3091c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 3092c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(!(x & 0x80)); 3093c74663799493f2b1e6123c18def94295d0afab7Kenny Root x |= 0x80; 3094c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3095c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) { 3096c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3097c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; 3098c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3099c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3100c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(local__fwrite(&x, 1, 1, *tempfile) != 1) { 3101c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3102c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3103c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3104c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3105c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3106c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3107c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)fclose(iterator->file); 3108c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3109c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status)) 3110c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3111c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3112c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(iterator->has_stats) 3113c74663799493f2b1e6123c18def94295d0afab7Kenny Root set_file_stats_(iterator->filename, &iterator->stats); 3114c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3115c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!simple_iterator_prime_input_(iterator, !iterator->is_writable)) 3116c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3117c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(backup) { 3118c74663799493f2b1e6123c18def94295d0afab7Kenny Root while(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length < save_offset) 3119c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(!FLAC__metadata_simple_iterator_next(iterator)) 3120c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3121c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 3122c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3123c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 3124c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* move the iterator to it's original block faster by faking a push, then doing a pop_ */ 3125c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(iterator->depth == 0); 3126c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->offset[0] = save_offset; 3127c74663799493f2b1e6123c18def94295d0afab7Kenny Root iterator->depth++; 3128c74663799493f2b1e6123c18def94295d0afab7Kenny Root return simple_iterator_pop_(iterator); 3129c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3130c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3131c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3132c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status) 3133c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3134c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[8192]; 3135c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t n; 3136c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3137c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(bytes >= 0); 3138c74663799493f2b1e6123c18def94295d0afab7Kenny Root while(bytes > 0) { 3139c74663799493f2b1e6123c18def94295d0afab7Kenny Root n = min(sizeof(buffer), (size_t)bytes); 3140c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(fread(buffer, 1, n, file) != n) { 3141c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3142c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3143c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3144c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(local__fwrite(buffer, 1, n, tempfile) != n) { 3145c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3146c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3147c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3148c74663799493f2b1e6123c18def94295d0afab7Kenny Root bytes -= n; 3149c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3150c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3151c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 3152c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3153c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3154c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__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, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status) 3155c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3156c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[8192]; 3157c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t n; 3158c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3159c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(bytes >= 0); 3160c74663799493f2b1e6123c18def94295d0afab7Kenny Root while(bytes > 0) { 3161c74663799493f2b1e6123c18def94295d0afab7Kenny Root n = min(sizeof(buffer), (size_t)bytes); 3162c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(read_cb(buffer, 1, n, handle) != n) { 3163c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3164c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3165c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3166c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(temp_write_cb(buffer, 1, n, temp_handle) != n) { 3167c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3168c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3169c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3170c74663799493f2b1e6123c18def94295d0afab7Kenny Root bytes -= n; 3171c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3172c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3173c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 3174c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3175c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3176c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status) 3177c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3178c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[8192]; 3179c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t n; 3180c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3181c74663799493f2b1e6123c18def94295d0afab7Kenny Root while(!feof(file)) { 3182c74663799493f2b1e6123c18def94295d0afab7Kenny Root n = fread(buffer, 1, sizeof(buffer), file); 3183c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(n == 0 && !feof(file)) { 3184c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3185c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3186c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3187c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(n > 0 && local__fwrite(buffer, 1, n, tempfile) != n) { 3188c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3189c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3190c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3191c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3192c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3193c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 3194c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3195c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3196c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__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) 3197c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3198c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__byte buffer[8192]; 3199c74663799493f2b1e6123c18def94295d0afab7Kenny Root size_t n; 3200c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3201c74663799493f2b1e6123c18def94295d0afab7Kenny Root while(!eof_cb(handle)) { 3202c74663799493f2b1e6123c18def94295d0afab7Kenny Root n = read_cb(buffer, 1, sizeof(buffer), handle); 3203c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(n == 0 && !eof_cb(handle)) { 3204c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; 3205c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3206c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3207c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(n > 0 && temp_write_cb(buffer, 1, n, temp_handle) != n) { 3208c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; 3209c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3210c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3211c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3212c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3213c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 3214c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3215c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3216c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status) 3217c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3218c74663799493f2b1e6123c18def94295d0afab7Kenny Root static const char *tempfile_suffix = ".metadata_edit"; 3219c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == tempfile_path_prefix) { 3220c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (*tempfilename = (char*)safe_malloc_add_3op_(strlen(filename), /*+*/strlen(tempfile_suffix), /*+*/1))) { 3221c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 3222c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3223c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3224c74663799493f2b1e6123c18def94295d0afab7Kenny Root strcpy(*tempfilename, filename); 3225c74663799493f2b1e6123c18def94295d0afab7Kenny Root strcat(*tempfilename, tempfile_suffix); 3226c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3227c74663799493f2b1e6123c18def94295d0afab7Kenny Root else { 3228c74663799493f2b1e6123c18def94295d0afab7Kenny Root const char *p = strrchr(filename, '/'); 3229c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == p) 3230c74663799493f2b1e6123c18def94295d0afab7Kenny Root p = filename; 3231c74663799493f2b1e6123c18def94295d0afab7Kenny Root else 3232c74663799493f2b1e6123c18def94295d0afab7Kenny Root p++; 3233c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3234c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (*tempfilename = (char*)safe_malloc_add_4op_(strlen(tempfile_path_prefix), /*+*/strlen(p), /*+*/strlen(tempfile_suffix), /*+*/2))) { 3235c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; 3236c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3237c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3238c74663799493f2b1e6123c18def94295d0afab7Kenny Root strcpy(*tempfilename, tempfile_path_prefix); 3239c74663799493f2b1e6123c18def94295d0afab7Kenny Root strcat(*tempfilename, "/"); 3240c74663799493f2b1e6123c18def94295d0afab7Kenny Root strcat(*tempfilename, p); 3241c74663799493f2b1e6123c18def94295d0afab7Kenny Root strcat(*tempfilename, tempfile_suffix); 3242c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3243c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3244c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) { 3245c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; 3246c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3247c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3248c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3249c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 3250c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3251c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3252c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status) 3253c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3254c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 3255c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != tempfile); 3256c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != *tempfile); 3257c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != tempfilename); 3258c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != *tempfilename); 3259c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != status); 3260c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3261c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)fclose(*tempfile); 3262c74663799493f2b1e6123c18def94295d0afab7Kenny Root *tempfile = 0; 3263c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3264c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__ 3265c74663799493f2b1e6123c18def94295d0afab7Kenny Root /* on some flavors of windows, rename() will fail if the destination already exists */ 3266c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(unlink(filename) < 0) { 3267c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3268c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR; 3269c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3270c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3271c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 3272c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3273c74663799493f2b1e6123c18def94295d0afab7Kenny Root /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just rename(): */ 3274c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != rename(*tempfilename, filename)) { 3275c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3276c74663799493f2b1e6123c18def94295d0afab7Kenny Root *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR; 3277c74663799493f2b1e6123c18def94295d0afab7Kenny Root return false; 3278c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3279c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3280c74663799493f2b1e6123c18def94295d0afab7Kenny Root cleanup_tempfile_(tempfile, tempfilename); 3281c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3282c74663799493f2b1e6123c18def94295d0afab7Kenny Root return true; 3283c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3284c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3285c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid cleanup_tempfile_(FILE **tempfile, char **tempfilename) 3286c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3287c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != *tempfile) { 3288c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)fclose(*tempfile); 3289c74663799493f2b1e6123c18def94295d0afab7Kenny Root *tempfile = 0; 3290c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3291c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3292c74663799493f2b1e6123c18def94295d0afab7Kenny Root if(0 != *tempfilename) { 3293c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)unlink(*tempfilename); 3294c74663799493f2b1e6123c18def94295d0afab7Kenny Root free(*tempfilename); 3295c74663799493f2b1e6123c18def94295d0afab7Kenny Root *tempfilename = 0; 3296c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3297c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3298c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3299c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__bool get_file_stats_(const char *filename, struct stat *stats) 3300c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3301c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 3302c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != stats); 3303c74663799493f2b1e6123c18def94295d0afab7Kenny Root return (0 == stat(filename, stats)); 3304c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3305c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3306c74663799493f2b1e6123c18def94295d0afab7Kenny Rootvoid set_file_stats_(const char *filename, struct stat *stats) 3307c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3308c74663799493f2b1e6123c18def94295d0afab7Kenny Root struct utimbuf srctime; 3309c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3310c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != filename); 3311c74663799493f2b1e6123c18def94295d0afab7Kenny Root FLAC__ASSERT(0 != stats); 3312c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3313c74663799493f2b1e6123c18def94295d0afab7Kenny Root srctime.actime = stats->st_atime; 3314c74663799493f2b1e6123c18def94295d0afab7Kenny Root srctime.modtime = stats->st_mtime; 3315c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)chmod(filename, stats->st_mode); 3316c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)utime(filename, &srctime); 3317c74663799493f2b1e6123c18def94295d0afab7Kenny Root#if !defined _MSC_VER && !defined __BORLANDC__ && !defined __MINGW32__ && !defined __EMX__ 3318c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)chown(filename, stats->st_uid, -1); 3319c74663799493f2b1e6123c18def94295d0afab7Kenny Root (void)chown(filename, -1, stats->st_gid); 3320c74663799493f2b1e6123c18def94295d0afab7Kenny Root#endif 3321c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3322c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3323c74663799493f2b1e6123c18def94295d0afab7Kenny Rootint fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence) 3324c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3325c74663799493f2b1e6123c18def94295d0afab7Kenny Root return fseeko((FILE*)handle, (off_t)offset, whence); 3326c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3327c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3328c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__int64 ftell_wrapper_(FLAC__IOHandle handle) 3329c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3330c74663799493f2b1e6123c18def94295d0afab7Kenny Root return ftello((FILE*)handle); 3331c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3332c74663799493f2b1e6123c18def94295d0afab7Kenny Root 3333c74663799493f2b1e6123c18def94295d0afab7Kenny RootFLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status) 3334c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 3335c74663799493f2b1e6123c18def94295d0afab7Kenny Root switch(status) { 3336c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK: 3337c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_OK; 3338c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT: 3339c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT; 3340c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE: 3341c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; 3342c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE: 3343c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE; 3344c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE: 3345c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE; 3346c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA: 3347c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA; 3348c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR: 3349c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_READ_ERROR; 3350c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR: 3351c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; 3352c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR: 3353c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; 3354c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR: 3355c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR; 3356c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR: 3357c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR; 3358c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR: 3359c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; 3360c74663799493f2b1e6123c18def94295d0afab7Kenny Root case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR: 3361c74663799493f2b1e6123c18def94295d0afab7Kenny Root default: 3362c74663799493f2b1e6123c18def94295d0afab7Kenny Root return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; 3363c74663799493f2b1e6123c18def94295d0afab7Kenny Root } 3364c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 3365