diff options
Diffstat (limited to 'src/libOggFLAC')
22 files changed, 1306 insertions, 4130 deletions
diff --git a/src/libOggFLAC/Makefile.am b/src/libOggFLAC/Makefile.am index aa4eaf3c..7b198eb1 100644 --- a/src/libOggFLAC/Makefile.am +++ b/src/libOggFLAC/Makefile.am @@ -51,13 +51,9 @@ libOggFLAC_la_LIBADD = @OGG_LIBS@ ../libFLAC/libFLAC.la libOggFLAC_la_LDFLAGS = -version-info 3:0:0 libOggFLAC_la_SOURCES = \ - file_decoder.c \ - file_encoder.c \ ogg_decoder_aspect.c \ ogg_encoder_aspect.c \ ogg_helper.c \ ogg_mapping.c \ - seekable_stream_decoder.c \ - seekable_stream_encoder.c \ stream_decoder.c \ stream_encoder.c diff --git a/src/libOggFLAC/Makefile.lite b/src/libOggFLAC/Makefile.lite index 9144a22f..1f10aed3 100644 --- a/src/libOggFLAC/Makefile.lite +++ b/src/libOggFLAC/Makefile.lite @@ -48,14 +48,10 @@ INCLUDES = -I./include -I$(topdir)/include -I$(OGG_INCLUDE_DIR) DEBUG_CFLAGS = SRCS_C = \ - file_decoder.c \ - file_encoder.c \ ogg_decoder_aspect.c \ ogg_encoder_aspect.c \ ogg_helper.c \ ogg_mapping.c \ - seekable_stream_decoder.c \ - seekable_stream_encoder.c \ stream_decoder.c \ stream_encoder.c diff --git a/src/libOggFLAC/file_decoder.c b/src/libOggFLAC/file_decoder.c deleted file mode 100644 index 926f6bc0..00000000 --- a/src/libOggFLAC/file_decoder.c +++ /dev/null @@ -1,672 +0,0 @@ -/* libOggFLAC - Free Lossless Audio Codec + Ogg library - * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if HAVE_CONFIG_H -# include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> /* for malloc() */ -#include <string.h> /* for strcmp() */ -#include <sys/stat.h> /* for stat() */ -#if defined _MSC_VER || defined __MINGW32__ -#include <io.h> /* for _setmode() */ -#include <fcntl.h> /* for _O_BINARY */ -#include <sys/types.h> /* for off_t */ -//@@@ [2G limit] hacks for MSVC6 -#define fseeko fseek -#define ftello ftell -#elif defined __CYGWIN__ -#include <io.h> /* for setmode(), O_BINARY */ -#include <fcntl.h> /* for _O_BINARY */ -#endif -#include "FLAC/assert.h" -#include "protected/file_decoder.h" -#include "protected/seekable_stream_decoder.h" - -/*********************************************************************** - * - * Private class method prototypes - * - ***********************************************************************/ - -static void set_defaults_(OggFLAC__FileDecoder *decoder); -static FILE *get_binary_stdin_(); -static OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); -static OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); -static OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); -static OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); -static FLAC__bool eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data); -static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); -static void metadata_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); -static void error_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); - -/*********************************************************************** - * - * Private class data - * - ***********************************************************************/ - -typedef struct OggFLAC__FileDecoderPrivate { - OggFLAC__FileDecoderWriteCallback write_callback; - OggFLAC__FileDecoderMetadataCallback metadata_callback; - OggFLAC__FileDecoderErrorCallback error_callback; - void *client_data; - FILE *file; - char *filename; /* == NULL if stdin */ - OggFLAC__SeekableStreamDecoder *seekable_stream_decoder; -} OggFLAC__FileDecoderPrivate; - -/*********************************************************************** - * - * Public static class data - * - ***********************************************************************/ - -OggFLAC_API const char * const OggFLAC__FileDecoderStateString[] = { - "OggFLAC__FILE_DECODER_OK", - "OggFLAC__FILE_DECODER_END_OF_FILE", - "OggFLAC__FILE_DECODER_ERROR_OPENING_FILE", - "OggFLAC__FILE_DECODER_SEEK_ERROR", - "OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR", - "OggFLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR", - "OggFLAC__FILE_DECODER_ALREADY_INITIALIZED", - "OggFLAC__FILE_DECODER_INVALID_CALLBACK", - "OggFLAC__FILE_DECODER_UNINITIALIZED" -}; - -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -OggFLAC_API OggFLAC__FileDecoder *OggFLAC__file_decoder_new() -{ - OggFLAC__FileDecoder *decoder; - - FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ - - decoder = (OggFLAC__FileDecoder*)calloc(1, sizeof(OggFLAC__FileDecoder)); - if(decoder == 0) { - return 0; - } - - decoder->protected_ = (OggFLAC__FileDecoderProtected*)calloc(1, sizeof(OggFLAC__FileDecoderProtected)); - if(decoder->protected_ == 0) { - free(decoder); - return 0; - } - - decoder->private_ = (OggFLAC__FileDecoderPrivate*)calloc(1, sizeof(OggFLAC__FileDecoderPrivate)); - if(decoder->private_ == 0) { - free(decoder->protected_); - free(decoder); - return 0; - } - - decoder->private_->seekable_stream_decoder = OggFLAC__seekable_stream_decoder_new(); - if(0 == decoder->private_->seekable_stream_decoder) { - free(decoder->private_); - free(decoder->protected_); - free(decoder); - return 0; - } - - decoder->private_->file = 0; - - set_defaults_(decoder); - - decoder->protected_->state = OggFLAC__FILE_DECODER_UNINITIALIZED; - - return decoder; -} - -OggFLAC_API void OggFLAC__file_decoder_delete(OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - - (void)OggFLAC__file_decoder_finish(decoder); - - OggFLAC__seekable_stream_decoder_delete(decoder->private_->seekable_stream_decoder); - - free(decoder->private_); - free(decoder->protected_); - free(decoder); -} - -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - -OggFLAC_API OggFLAC__FileDecoderState OggFLAC__file_decoder_init(OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return decoder->protected_->state = OggFLAC__FILE_DECODER_ALREADY_INITIALIZED; - - if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback) - return decoder->protected_->state = OggFLAC__FILE_DECODER_INVALID_CALLBACK; - - if(0 == decoder->private_->filename) - decoder->private_->file = get_binary_stdin_(); - else - decoder->private_->file = fopen(decoder->private_->filename, "rb"); - - if(decoder->private_->file == 0) - return decoder->protected_->state = OggFLAC__FILE_DECODER_ERROR_OPENING_FILE; - - OggFLAC__seekable_stream_decoder_set_read_callback(decoder->private_->seekable_stream_decoder, read_callback_); - OggFLAC__seekable_stream_decoder_set_seek_callback(decoder->private_->seekable_stream_decoder, seek_callback_); - OggFLAC__seekable_stream_decoder_set_tell_callback(decoder->private_->seekable_stream_decoder, tell_callback_); - OggFLAC__seekable_stream_decoder_set_length_callback(decoder->private_->seekable_stream_decoder, length_callback_); - OggFLAC__seekable_stream_decoder_set_eof_callback(decoder->private_->seekable_stream_decoder, eof_callback_); - OggFLAC__seekable_stream_decoder_set_write_callback(decoder->private_->seekable_stream_decoder, write_callback_); - OggFLAC__seekable_stream_decoder_set_metadata_callback(decoder->private_->seekable_stream_decoder, metadata_callback_); - OggFLAC__seekable_stream_decoder_set_error_callback(decoder->private_->seekable_stream_decoder, error_callback_); - OggFLAC__seekable_stream_decoder_set_client_data(decoder->private_->seekable_stream_decoder, decoder); - - if(OggFLAC__seekable_stream_decoder_init(decoder->private_->seekable_stream_decoder) != OggFLAC__SEEKABLE_STREAM_DECODER_OK) - return decoder->protected_->state = OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR; - - return decoder->protected_->state = OggFLAC__FILE_DECODER_OK; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_finish(OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - - if(decoder->protected_->state == OggFLAC__FILE_DECODER_UNINITIALIZED) - return true; - - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - - if(0 != decoder->private_->file && decoder->private_->file != stdin) { - fclose(decoder->private_->file); - decoder->private_->file = 0; - } - - if(0 != decoder->private_->filename) { - free(decoder->private_->filename); - decoder->private_->filename = 0; - } - - set_defaults_(decoder); - - decoder->protected_->state = OggFLAC__FILE_DECODER_UNINITIALIZED; - - return OggFLAC__seekable_stream_decoder_finish(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_md5_checking(OggFLAC__FileDecoder *decoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_decoder_set_md5_checking(decoder->private_->seekable_stream_decoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_filename(OggFLAC__FileDecoder *decoder, const char *value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != value); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - if(0 != decoder->private_->filename) { - free(decoder->private_->filename); - decoder->private_->filename = 0; - } - if(0 != strcmp(value, "-")) { - if(0 == (decoder->private_->filename = (char*)malloc(strlen(value)+1))) { - decoder->protected_->state = OggFLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - strcpy(decoder->private_->filename, value); - } - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_write_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderWriteCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - decoder->private_->write_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderMetadataCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - decoder->private_->metadata_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_error_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderErrorCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - decoder->private_->error_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_client_data(OggFLAC__FileDecoder *decoder, void *value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - decoder->private_->client_data = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_serial_number(OggFLAC__FileDecoder *decoder, long value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - OggFLAC__seekable_stream_decoder_set_serial_number(decoder->private_->seekable_stream_decoder, value); - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond(OggFLAC__FileDecoder *decoder, FLAC__MetadataType type) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder->private_->seekable_stream_decoder, type); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond_application(OggFLAC__FileDecoder *decoder, const FLAC__byte id[4]) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_decoder_set_metadata_respond_application(decoder->private_->seekable_stream_decoder, id); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond_all(OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore(OggFLAC__FileDecoder *decoder, FLAC__MetadataType type) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_decoder_set_metadata_ignore(decoder->private_->seekable_stream_decoder, type); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore_application(OggFLAC__FileDecoder *decoder, const FLAC__byte id[4]) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder->private_->seekable_stream_decoder, id); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore_all(OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder); - if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API OggFLAC__FileDecoderState OggFLAC__file_decoder_get_state(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->state; -} - -OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_seekable_stream_decoder_state(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_state(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__file_decoder_get_stream_decoder_state(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_decoder_get_FLAC_stream_decoder_state(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API const char *OggFLAC__file_decoder_get_resolved_state_string(const OggFLAC__FileDecoder *decoder) -{ - if(decoder->protected_->state != OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) - return OggFLAC__FileDecoderStateString[decoder->protected_->state]; - else - return OggFLAC__seekable_stream_decoder_get_resolved_state_string(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_get_md5_checking(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_md5_checking(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API unsigned OggFLAC__file_decoder_get_channels(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_channels(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API FLAC__ChannelAssignment OggFLAC__file_decoder_get_channel_assignment(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_channel_assignment(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API unsigned OggFLAC__file_decoder_get_bits_per_sample(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_bits_per_sample(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API unsigned OggFLAC__file_decoder_get_sample_rate(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_sample_rate(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__seekable_stream_decoder_get_blocksize(decoder->private_->seekable_stream_decoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_single(OggFLAC__FileDecoder *decoder) -{ - FLAC__bool ret; - FLAC__ASSERT(0 != decoder); - - if(decoder->private_->seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) - decoder->protected_->state = OggFLAC__FILE_DECODER_END_OF_FILE; - - if(decoder->protected_->state == OggFLAC__FILE_DECODER_END_OF_FILE) - return true; - - FLAC__ASSERT(decoder->protected_->state == OggFLAC__FILE_DECODER_OK); - - ret = OggFLAC__seekable_stream_decoder_process_single(decoder->private_->seekable_stream_decoder); - if(!ret) - decoder->protected_->state = OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR; - - return ret; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_metadata(OggFLAC__FileDecoder *decoder) -{ - FLAC__bool ret; - FLAC__ASSERT(0 != decoder); - - if(decoder->private_->seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) - decoder->protected_->state = OggFLAC__FILE_DECODER_END_OF_FILE; - - if(decoder->protected_->state == OggFLAC__FILE_DECODER_END_OF_FILE) - return true; - - FLAC__ASSERT(decoder->protected_->state == OggFLAC__FILE_DECODER_OK); - - ret = OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder->private_->seekable_stream_decoder); - if(!ret) - decoder->protected_->state = OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR; - - return ret; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_file(OggFLAC__FileDecoder *decoder) -{ - FLAC__bool ret; - FLAC__ASSERT(0 != decoder); - - if(decoder->private_->seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) - decoder->protected_->state = OggFLAC__FILE_DECODER_END_OF_FILE; - - if(decoder->protected_->state == OggFLAC__FILE_DECODER_END_OF_FILE) - return true; - - FLAC__ASSERT(decoder->protected_->state == OggFLAC__FILE_DECODER_OK); - - ret = OggFLAC__seekable_stream_decoder_process_until_end_of_stream(decoder->private_->seekable_stream_decoder); - if(!ret) - decoder->protected_->state = OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR; - - return ret; -} - -OggFLAC_API FLAC__bool OggFLAC__file_decoder_seek_absolute(OggFLAC__FileDecoder *decoder, FLAC__uint64 sample) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(decoder->protected_->state == OggFLAC__FILE_DECODER_OK || decoder->protected_->state == OggFLAC__FILE_DECODER_END_OF_FILE); - - if(decoder->private_->filename == 0) { /* means the file is stdin... */ - decoder->protected_->state = OggFLAC__FILE_DECODER_SEEK_ERROR; - return false; - } - - if(!OggFLAC__seekable_stream_decoder_seek_absolute(decoder->private_->seekable_stream_decoder, sample)) { - decoder->protected_->state = OggFLAC__FILE_DECODER_SEEK_ERROR; - return false; - } - else { - decoder->protected_->state = OggFLAC__FILE_DECODER_OK; - return true; - } -} - - -/*********************************************************************** - * - * Private class methods - * - ***********************************************************************/ - -void set_defaults_(OggFLAC__FileDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - - decoder->private_->filename = 0; - decoder->private_->write_callback = 0; - decoder->private_->metadata_callback = 0; - decoder->private_->error_callback = 0; - decoder->private_->client_data = 0; -} - -/* - * This will forcibly set stdin to binary mode (for OSes that require it) - */ -FILE *get_binary_stdin_() -{ - /* if something breaks here it is probably due to the presence or - * absence of an underscore before the identifiers 'setmode', - * 'fileno', and/or 'O_BINARY'; check your system header files. - */ -#if defined _MSC_VER || defined __MINGW32__ - _setmode(_fileno(stdin), _O_BINARY); -#elif defined __CYGWIN__ - /* almost certainly not needed for any modern Cygwin, but let's be safe... */ - setmode(_fileno(stdin), _O_BINARY); -#endif - - return stdin; -} - -OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) -{ - OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; - (void)decoder; - - if(*bytes > 0) { - *bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, file_decoder->private_->file); - if(ferror(file_decoder->private_->file)) { - return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; - } - else { - return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; - } - } - else - return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */ -} - -OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) -{ - OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; - (void)decoder; - - if(fseeko(file_decoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) - return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; - else - return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; -} - -OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) -{ - OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; - off_t pos; - (void)decoder; - - if((pos = ftello(file_decoder->private_->file)) < 0) - return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; - else { - *absolute_byte_offset = (FLAC__uint64)pos; - return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; - } -} - -OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) -{ - OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; - struct stat filestats; - (void)decoder; - - if(0 == file_decoder->private_->filename || stat(file_decoder->private_->filename, &filestats) != 0) - return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; - else { - *stream_length = (FLAC__uint64)filestats.st_size; - return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; - } -} - -FLAC__bool eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data) -{ - OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; - (void)decoder; - - return feof(file_decoder->private_->file)? true : false; -} - -FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) -{ - OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; - (void)decoder; - - return file_decoder->private_->write_callback(file_decoder, frame, buffer, file_decoder->private_->client_data); -} - -void metadata_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) -{ - OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; - (void)decoder; - - file_decoder->private_->metadata_callback(file_decoder, metadata, file_decoder->private_->client_data); -} - -void error_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) -{ - OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; - (void)decoder; - - file_decoder->private_->error_callback(file_decoder, status, file_decoder->private_->client_data); -} diff --git a/src/libOggFLAC/file_encoder.c b/src/libOggFLAC/file_encoder.c deleted file mode 100644 index e9e2821a..00000000 --- a/src/libOggFLAC/file_encoder.c +++ /dev/null @@ -1,835 +0,0 @@ -/* libOggFLAC - Free Lossless Audio Codec + Ogg library - * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if HAVE_CONFIG_H -# include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> /* for malloc() */ -#include <string.h> /* for strlen(), strcpy() */ -#if defined _MSC_VER || defined __MINGW32__ -#include <sys/types.h> /* for off_t */ -//@@@ [2G limit] hacks for MSVC6 -#define fseeko fseek -#define ftello ftell -#endif -#include "FLAC/assert.h" -#include "OggFLAC/seekable_stream_encoder.h" -#include "protected/file_encoder.h" - -#ifdef max -#undef max -#endif -#define max(x,y) ((x)>(y)?(x):(y)) - -/*********************************************************************** - * - * Private class method prototypes - * - ***********************************************************************/ - -/* unpublished debug routines */ -extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_constant_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value); -extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_fixed_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value); -extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value); - -static void set_defaults_(OggFLAC__FileEncoder *encoder); -static OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); -static FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data); -static FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data); -static FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); - -/*********************************************************************** - * - * Private class data - * - ***********************************************************************/ - -typedef struct OggFLAC__FileEncoderPrivate { - OggFLAC__FileEncoderProgressCallback progress_callback; - void *client_data; - char *filename; - FLAC__uint64 bytes_written; - FLAC__uint64 samples_written; - unsigned frames_written; - unsigned total_frames_estimate; - OggFLAC__SeekableStreamEncoder *seekable_stream_encoder; - FILE *file; -} OggFLAC__FileEncoderPrivate; - -/*********************************************************************** - * - * Public static class data - * - ***********************************************************************/ - -OggFLAC_API const char * const OggFLAC__FileEncoderStateString[] = { - "OggFLAC__FILE_ENCODER_OK", - "OggFLAC__FILE_ENCODER_NO_FILENAME", - "OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR", - "OggFLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING", - "OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE", - "OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR", - "OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED", - "OggFLAC__FILE_ENCODER_UNINITIALIZED" -}; - - -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -OggFLAC_API OggFLAC__FileEncoder *OggFLAC__file_encoder_new() -{ - OggFLAC__FileEncoder *encoder; - - FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ - - encoder = (OggFLAC__FileEncoder*)calloc(1, sizeof(OggFLAC__FileEncoder)); - if(encoder == 0) { - return 0; - } - - encoder->protected_ = (OggFLAC__FileEncoderProtected*)calloc(1, sizeof(OggFLAC__FileEncoderProtected)); - if(encoder->protected_ == 0) { - free(encoder); - return 0; - } - - encoder->private_ = (OggFLAC__FileEncoderPrivate*)calloc(1, sizeof(OggFLAC__FileEncoderPrivate)); - if(encoder->private_ == 0) { - free(encoder->protected_); - free(encoder); - return 0; - } - - encoder->private_->seekable_stream_encoder = OggFLAC__seekable_stream_encoder_new(); - if(0 == encoder->private_->seekable_stream_encoder) { - free(encoder->private_); - free(encoder->protected_); - free(encoder); - return 0; - } - - encoder->private_->file = 0; - - set_defaults_(encoder); - - encoder->protected_->state = OggFLAC__FILE_ENCODER_UNINITIALIZED; - - return encoder; -} - -OggFLAC_API void OggFLAC__file_encoder_delete(OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - - (void)OggFLAC__file_encoder_finish(encoder); - - OggFLAC__seekable_stream_encoder_delete(encoder->private_->seekable_stream_encoder); - - free(encoder->private_); - free(encoder->protected_); - free(encoder); -} - -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - -OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_init(OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return encoder->protected_->state = OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED; - - if(0 == encoder->private_->filename) - return encoder->protected_->state = OggFLAC__FILE_ENCODER_NO_FILENAME; - - encoder->private_->file = fopen(encoder->private_->filename, "w+b"); - - if(encoder->private_->file == 0) - return encoder->protected_->state = OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE; - - encoder->private_->bytes_written = 0; - encoder->private_->samples_written = 0; - encoder->private_->frames_written = 0; - - OggFLAC__seekable_stream_encoder_set_read_callback(encoder->private_->seekable_stream_encoder, read_callback_); - OggFLAC__seekable_stream_encoder_set_seek_callback(encoder->private_->seekable_stream_encoder, seek_callback_); - OggFLAC__seekable_stream_encoder_set_tell_callback(encoder->private_->seekable_stream_encoder, tell_callback_); - OggFLAC__seekable_stream_encoder_set_write_callback(encoder->private_->seekable_stream_encoder, write_callback_); - OggFLAC__seekable_stream_encoder_set_client_data(encoder->private_->seekable_stream_encoder, encoder); - - if(OggFLAC__seekable_stream_encoder_init(encoder->private_->seekable_stream_encoder) != OggFLAC__SEEKABLE_STREAM_ENCODER_OK) - return encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR; - - { - unsigned blocksize = OggFLAC__file_encoder_get_blocksize(encoder); - - FLAC__ASSERT(blocksize != 0); - encoder->private_->total_frames_estimate = (unsigned)((OggFLAC__file_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize); - } - - return encoder->protected_->state = OggFLAC__FILE_ENCODER_OK; -} - -OggFLAC_API void OggFLAC__file_encoder_finish(OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - - if(encoder->protected_->state == OggFLAC__FILE_ENCODER_UNINITIALIZED) - return; - - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - - /* OggFLAC__seekable_stream_encoder_finish() might write data so we must close the file after it. */ - - OggFLAC__seekable_stream_encoder_finish(encoder->private_->seekable_stream_encoder); - - if(0 != encoder->private_->file) { - fclose(encoder->private_->file); - encoder->private_->file = 0; - } - - if(0 != encoder->private_->filename) { - free(encoder->private_->filename); - encoder->private_->filename = 0; - } - - set_defaults_(encoder); - - encoder->protected_->state = OggFLAC__FILE_ENCODER_UNINITIALIZED; -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_serial_number(OggFLAC__FileEncoder *encoder, long serial_number) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_serial_number(encoder->private_->seekable_stream_encoder, serial_number); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_verify(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_verify(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_streamable_subset(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_streamable_subset(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_loose_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_channels(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_channels(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_bits_per_sample(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_bits_per_sample(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_sample_rate(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_sample_rate(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_blocksize(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_blocksize(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_apodization(OggFLAC__FileEncoder *encoder, const char *specification) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_apodization(encoder->private_->seekable_stream_encoder, specification); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_lpc_order(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_max_lpc_order(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_qlp_coeff_precision(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_escape_coding(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_do_escape_coding(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_exhaustive_model_search(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_min_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_rice_parameter_search_dist(OggFLAC__FileEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_total_samples_estimate(OggFLAC__FileEncoder *encoder, FLAC__uint64 value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_total_samples_estimate(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_metadata(OggFLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_set_metadata(encoder->private_->seekable_stream_encoder, metadata, num_blocks); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_filename(OggFLAC__FileEncoder *encoder, const char *value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != value); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - if(0 != encoder->private_->filename) { - free(encoder->private_->filename); - encoder->private_->filename = 0; - } - if(0 == (encoder->private_->filename = (char*)malloc(strlen(value)+1))) { - encoder->protected_->state = OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR; - return false; - } - strcpy(encoder->private_->filename, value); - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_progress_callback(OggFLAC__FileEncoder *encoder, OggFLAC__FileEncoderProgressCallback value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - encoder->private_->progress_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_client_data(OggFLAC__FileEncoder *encoder, void *value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - encoder->private_->client_data = value; - return true; -} - -/* - * These three functions are not static, but not publically exposed in - * include/OggFLAC/ either. They are used by the test suite. - */ -OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_constant_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_disable_constant_subframes(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_fixed_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_disable_fixed_subframes(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_verbatim_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED) - return false; - return OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(encoder->private_->seekable_stream_encoder, value); -} - -OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_get_state(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->protected_); - return encoder->protected_->state; -} - -OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__file_encoder_get_seekable_stream_encoder_state(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_state(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__StreamEncoderState OggFLAC__file_encoder_get_FLAC_stream_encoder_state(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_encoder_get_verify_decoder_state(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_verify_decoder_state(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API const char *OggFLAC__file_encoder_get_resolved_state_string(const OggFLAC__FileEncoder *encoder) -{ - if(encoder->protected_->state != OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR) - return OggFLAC__FileEncoderStateString[encoder->protected_->state]; - else - return OggFLAC__seekable_stream_encoder_get_resolved_state_string(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API void OggFLAC__file_encoder_get_verify_decoder_error_stats(const OggFLAC__FileEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder->private_->seekable_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_verify(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_verify(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_streamable_subset(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_streamable_subset(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_mid_side_stereo(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_loose_mid_side_stereo(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_channels(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_channels(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_bits_per_sample(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_bits_per_sample(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_sample_rate(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_sample_rate(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_blocksize(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_blocksize(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_max_lpc_order(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_max_lpc_order(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_qlp_coeff_precision(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_escape_coding(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_do_escape_coding(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_exhaustive_model_search(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_min_residual_partition_order(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_max_residual_partition_order(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__file_encoder_get_rice_parameter_search_dist(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__uint64 OggFLAC__file_encoder_get_total_samples_estimate(const OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - return OggFLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->seekable_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__file_encoder_process(OggFLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - if(!OggFLAC__seekable_stream_encoder_process(encoder->private_->seekable_stream_encoder, buffer, samples)) { - encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR; - return false; - } - else - return true; -} - -/* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */ -OggFLAC_API FLAC__bool OggFLAC__file_encoder_process_interleaved(OggFLAC__FileEncoder *encoder, const FLAC__int32 buffer[], unsigned samples) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - if(!OggFLAC__seekable_stream_encoder_process_interleaved(encoder->private_->seekable_stream_encoder, buffer, samples)) { - encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR; - return false; - } - else - return true; -} - - -/*********************************************************************** - * - * Private class methods - * - ***********************************************************************/ - -void set_defaults_(OggFLAC__FileEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - - encoder->private_->progress_callback = 0; - encoder->private_->client_data = 0; - encoder->private_->total_frames_estimate = 0; - encoder->private_->filename = 0; -} - -OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) -{ - OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data; - - (void)encoder; - - FLAC__ASSERT(0 != file_encoder); - - *bytes = (unsigned)fread(buffer, 1, *bytes, file_encoder->private_->file); - if (*bytes == 0) { - if (feof(file_encoder->private_->file)) - return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM; - else if (ferror(file_encoder->private_->file)) - return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT; - } - return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE; -} - -FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data) -{ - OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data; - - (void)encoder; - - FLAC__ASSERT(0 != file_encoder); - - if(fseeko(file_encoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) - return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR; - else - return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK; -} - -FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) -{ - OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data; - off_t offset; - - (void)encoder; - - FLAC__ASSERT(0 != file_encoder); - - offset = ftello(file_encoder->private_->file); - - if(offset < 0) { - return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_ERROR; - } - else { - *absolute_byte_offset = (FLAC__uint64)offset; - return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK; - } -} - -#ifdef FLAC__VALGRIND_TESTING -static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) -{ - size_t ret = fwrite(ptr, size, nmemb, stream); - if(!ferror(stream)) - fflush(stream); - return ret; -} -#else -#define local__fwrite fwrite -#endif - -FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) -{ - OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data; - - (void)encoder; - - FLAC__ASSERT(0 != file_encoder); - - if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, file_encoder->private_->file) == bytes) { - file_encoder->private_->bytes_written += bytes; - file_encoder->private_->samples_written += samples; - /* we keep a high watermark on the number of frames written - * because when the encoder goes back to write metadata, - * 'current_frame' will drop back to 0. - */ - file_encoder->private_->frames_written = max(file_encoder->private_->frames_written, current_frame+1); - /*@@@ We would like to add an '&& samples > 0' to the if - * clause here but currently because of the nature of our Ogg - * writing implementation, 'samples' is always 0 (see - * ogg_encoder_aspect.c). The downside is extra progress - * callbacks. - */ - if(0 != file_encoder->private_->progress_callback) - file_encoder->private_->progress_callback(file_encoder, file_encoder->private_->bytes_written, file_encoder->private_->samples_written, file_encoder->private_->frames_written, file_encoder->private_->total_frames_estimate, file_encoder->private_->client_data); - return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; - } - else - return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; -} diff --git a/src/libOggFLAC/include/private/ogg_decoder_aspect.h b/src/libOggFLAC/include/private/ogg_decoder_aspect.h index fab57d9d..ba5c3d22 100644 --- a/src/libOggFLAC/include/private/ogg_decoder_aspect.h +++ b/src/libOggFLAC/include/private/ogg_decoder_aspect.h @@ -36,6 +36,7 @@ #include "FLAC/ordinals.h" #include "FLAC/stream_decoder.h" /* for FLAC__StreamDecoderReadStatus */ +#include "OggFLAC/stream_decoder.h" typedef struct OggFLAC__OggDecoderAspect { /* these are storage for values that can be set through the API */ @@ -74,6 +75,6 @@ typedef enum { typedef OggFLAC__OggDecoderAspectReadStatus (*OggFLAC__OggDecoderAspectReadCallbackProxy)(const void *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); -OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, void *decoder, void *client_data); +OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, const OggFLAC__StreamDecoder *decoder, void *client_data); #endif diff --git a/src/libOggFLAC/include/private/ogg_helper.h b/src/libOggFLAC/include/private/ogg_helper.h index 49f30969..5a0cfafd 100644 --- a/src/libOggFLAC/include/private/ogg_helper.h +++ b/src/libOggFLAC/include/private/ogg_helper.h @@ -33,11 +33,11 @@ #define OggFLAC__PRIVATE__OGG_HELPER_H #include <ogg/ogg.h> -#include "OggFLAC/seekable_stream_encoder.h" /* for OggFLAC__SeekableStreamEncoder */ +#include "OggFLAC/stream_encoder.h" /* for OggFLAC__StreamEncoder */ void simple_ogg_page__init(ogg_page *page); void simple_ogg_page__clear(ogg_page *page); -FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data); -FLAC__bool simple_ogg_page__set_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderWriteCallback write_callback, void *client_data); +FLAC__bool simple_ogg_page__get_at(OggFLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, OggFLAC__StreamEncoderReadCallback read_callback, void *client_data); +FLAC__bool simple_ogg_page__set_at(OggFLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data); #endif diff --git a/src/libOggFLAC/include/protected/Makefile.am b/src/libOggFLAC/include/protected/Makefile.am index 552461df..fd7b6f91 100644 --- a/src/libOggFLAC/include/protected/Makefile.am +++ b/src/libOggFLAC/include/protected/Makefile.am @@ -30,9 +30,5 @@ noinst_HEADERS = \ all.h \ - file_decoder.h \ - file_encoder.h \ - seekable_stream_decoder.h \ - seekable_stream_encoder.h \ stream_decoder.h \ stream_encoder.h diff --git a/src/libOggFLAC/include/protected/all.h b/src/libOggFLAC/include/protected/all.h index ebbb2701..35940791 100644 --- a/src/libOggFLAC/include/protected/all.h +++ b/src/libOggFLAC/include/protected/all.h @@ -32,10 +32,6 @@ #ifndef OggFLAC__PROTECTED__ALL_H #define OggFLAC__PROTECTED__ALL_H -#include "file_decoder.h" -#include "file_encoder.h" -#include "seekable_stream_decoder.h" -#include "seekable_stream_encoder.h" #include "stream_decoder.h" #include "stream_encoder.h" diff --git a/src/libOggFLAC/include/protected/file_decoder.h b/src/libOggFLAC/include/protected/file_decoder.h deleted file mode 100644 index ba130a17..00000000 --- a/src/libOggFLAC/include/protected/file_decoder.h +++ /dev/null @@ -1,41 +0,0 @@ -/* libOggFLAC - Free Lossless Audio Codec + Ogg library - * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef OggFLAC__PROTECTED__FILE_DECODER_H -#define OggFLAC__PROTECTED__FILE_DECODER_H - -#include "OggFLAC/file_decoder.h" - -typedef struct OggFLAC__FileDecoderProtected { - OggFLAC__FileDecoderState state; -} OggFLAC__FileDecoderProtected; - -#endif diff --git a/src/libOggFLAC/include/protected/file_encoder.h b/src/libOggFLAC/include/protected/file_encoder.h deleted file mode 100644 index 0d850fd0..00000000 --- a/src/libOggFLAC/include/protected/file_encoder.h +++ /dev/null @@ -1,41 +0,0 @@ -/* libOggFLAC - Free Lossless Audio Codec + Ogg library - * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef OggFLAC__PROTECTED__FILE_ENCODER_H -#define OggFLAC__PROTECTED__FILE_ENCODER_H - -#include "OggFLAC/file_encoder.h" - -typedef struct OggFLAC__FileEncoderProtected { - OggFLAC__FileEncoderState state; -} OggFLAC__FileEncoderProtected; - -#endif diff --git a/src/libOggFLAC/include/protected/seekable_stream_decoder.h b/src/libOggFLAC/include/protected/seekable_stream_decoder.h deleted file mode 100644 index 92393237..00000000 --- a/src/libOggFLAC/include/protected/seekable_stream_decoder.h +++ /dev/null @@ -1,42 +0,0 @@ -/* libOggFLAC - Free Lossless Audio Codec + Ogg library - * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef OggFLAC__PROTECTED__SEEKABLE_STREAM_DECODER_H -#define OggFLAC__PROTECTED__SEEKABLE_STREAM_DECODER_H - -#include "OggFLAC/seekable_stream_decoder.h" - -typedef struct OggFLAC__SeekableStreamDecoderProtected { - FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */ - OggFLAC__SeekableStreamDecoderState state; -} OggFLAC__SeekableStreamDecoderProtected; - -#endif diff --git a/src/libOggFLAC/include/protected/seekable_stream_encoder.h b/src/libOggFLAC/include/protected/seekable_stream_encoder.h deleted file mode 100644 index 0f2f3b93..00000000 --- a/src/libOggFLAC/include/protected/seekable_stream_encoder.h +++ /dev/null @@ -1,44 +0,0 @@ -/* libOggFLAC - Free Lossless Audio Codec + Ogg library - * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef OggFLAC__PROTECTED__SEEKABLE_STREAM_ENCODER_H -#define OggFLAC__PROTECTED__SEEKABLE_STREAM_ENCODER_H - -#include "OggFLAC/seekable_stream_encoder.h" -#include "private/ogg_encoder_aspect.h" - -typedef struct OggFLAC__SeekableStreamEncoderProtected { - OggFLAC__SeekableStreamEncoderState state; - OggFLAC__OggEncoderAspect ogg_encoder_aspect; - FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset; -} OggFLAC__SeekableStreamEncoderProtected; - -#endif diff --git a/src/libOggFLAC/include/protected/stream_encoder.h b/src/libOggFLAC/include/protected/stream_encoder.h index e737c368..a47a4674 100644 --- a/src/libOggFLAC/include/protected/stream_encoder.h +++ b/src/libOggFLAC/include/protected/stream_encoder.h @@ -38,6 +38,7 @@ typedef struct OggFLAC__StreamEncoderProtected { OggFLAC__StreamEncoderState state; OggFLAC__OggEncoderAspect ogg_encoder_aspect; + FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset; } OggFLAC__StreamEncoderProtected; #endif diff --git a/src/libOggFLAC/libOggFLAC_dynamic.dsp b/src/libOggFLAC/libOggFLAC_dynamic.dsp index 944d7c4e..0f630d63 100644 --- a/src/libOggFLAC/libOggFLAC_dynamic.dsp +++ b/src/libOggFLAC/libOggFLAC_dynamic.dsp @@ -92,14 +92,6 @@ LINK32=link.exe # PROP Default_Filter "c"
# Begin Source File
-SOURCE=.\file_decoder.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_encoder.c
-# End Source File
-# Begin Source File
-
SOURCE=.\ogg_decoder_aspect.c
# End Source File
# Begin Source File
@@ -116,14 +108,6 @@ SOURCE=.\ogg_mapping.c # End Source File
# Begin Source File
-SOURCE=.\seekable_stream_decoder.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\seekable_stream_encoder.c
-# End Source File
-# Begin Source File
-
SOURCE=.\stream_decoder.c
# End Source File
# Begin Source File
@@ -164,22 +148,6 @@ SOURCE=.\include\protected\all.h # End Source File
# Begin Source File
-SOURCE=.\include\protected\file_decoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\protected\file_encoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\protected\seekable_stream_decoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\protected\seekable_stream_encoder.h
-# End Source File
-# Begin Source File
-
SOURCE=.\include\protected\stream_decoder.h
# End Source File
# Begin Source File
@@ -200,22 +168,6 @@ SOURCE=..\..\include\OggFLAC\export.h # End Source File
# Begin Source File
-SOURCE=..\..\include\OggFLAC\file_decoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\OggFLAC\file_encoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\OggFLAC\seekable_stream_decoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\OggFLAC\seekable_stream_encoder.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\OggFLAC\stream_decoder.h
# End Source File
# Begin Source File
diff --git a/src/libOggFLAC/libOggFLAC_static.dsp b/src/libOggFLAC/libOggFLAC_static.dsp index 3cf1c22c..466512af 100644 --- a/src/libOggFLAC/libOggFLAC_static.dsp +++ b/src/libOggFLAC/libOggFLAC_static.dsp @@ -85,14 +85,6 @@ LIB32=link.exe -lib # PROP Default_Filter "c"
# Begin Source File
-SOURCE=.\file_decoder.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\file_encoder.c
-# End Source File
-# Begin Source File
-
SOURCE=.\ogg_decoder_aspect.c
# End Source File
# Begin Source File
@@ -109,14 +101,6 @@ SOURCE=.\ogg_mapping.c # End Source File
# Begin Source File
-SOURCE=.\seekable_stream_decoder.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\seekable_stream_encoder.c
-# End Source File
-# Begin Source File
-
SOURCE=.\stream_decoder.c
# End Source File
# Begin Source File
@@ -157,22 +141,6 @@ SOURCE=.\include\protected\all.h # End Source File
# Begin Source File
-SOURCE=.\include\protected\file_decoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\protected\file_encoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\protected\seekable_stream_decoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\include\protected\seekable_stream_encoder.h
-# End Source File
-# Begin Source File
-
SOURCE=.\include\protected\stream_decoder.h
# End Source File
# Begin Source File
@@ -193,22 +161,6 @@ SOURCE=..\..\include\OggFLAC\export.h # End Source File
# Begin Source File
-SOURCE=..\..\include\OggFLAC\file_decoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\OggFLAC\file_encoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\OggFLAC\seekable_stream_decoder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\include\OggFLAC\seekable_stream_encoder.h
-# End Source File
-# Begin Source File
-
SOURCE=..\..\include\OggFLAC\stream_decoder.h
# End Source File
# Begin Source File
diff --git a/src/libOggFLAC/ogg_decoder_aspect.c b/src/libOggFLAC/ogg_decoder_aspect.c index 06e2852e..a85dd723 100644 --- a/src/libOggFLAC/ogg_decoder_aspect.c +++ b/src/libOggFLAC/ogg_decoder_aspect.c @@ -102,7 +102,7 @@ void OggFLAC__ogg_decoder_aspect_reset(OggFLAC__OggDecoderAspect *aspect) aspect->need_serial_number = true; } -OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, void *decoder, void *client_data) +OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, const OggFLAC__StreamDecoder *decoder, void *client_data) { static const unsigned OGG_BYTES_CHUNK = 8192; const unsigned bytes_requested = *bytes; diff --git a/src/libOggFLAC/ogg_encoder_aspect.c b/src/libOggFLAC/ogg_encoder_aspect.c index 0ca9eed6..29796d39 100644 --- a/src/libOggFLAC/ogg_encoder_aspect.c +++ b/src/libOggFLAC/ogg_encoder_aspect.c @@ -141,7 +141,7 @@ FLAC__StreamEncoderWriteStatus OggFLAC__ogg_encoder_aspect_write_callback_wrappe if(bytes != FLAC__STREAM_METADATA_HEADER_LENGTH + FLAC__STREAM_METADATA_STREAMINFO_LENGTH) { /* * If we get here, our assumption about the way write callbacks happen - * explained above is wrong + * (explained above) is wrong */ FLAC__ASSERT(0); return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; diff --git a/src/libOggFLAC/ogg_helper.c b/src/libOggFLAC/ogg_helper.c index bebd7f06..ca985553 100644 --- a/src/libOggFLAC/ogg_helper.c +++ b/src/libOggFLAC/ogg_helper.c @@ -37,33 +37,35 @@ #include <string.h> /* for memcmp(), memcpy() */ #include "FLAC/assert.h" #include "private/ogg_helper.h" -#include "protected/seekable_stream_encoder.h" +#include "protected/stream_encoder.h" -static FLAC__bool full_read_(OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte *buffer, unsigned bytes, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data) +static FLAC__bool full_read_(OggFLAC__StreamEncoder *encoder, FLAC__byte *buffer, unsigned bytes, OggFLAC__StreamEncoderReadCallback read_callback, void *client_data) { while(bytes > 0) { unsigned bytes_read = bytes; switch(read_callback(encoder, buffer, &bytes_read, client_data)) { - case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE: + case OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE: bytes -= bytes_read; buffer += bytes_read; break; - case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM: + case OggFLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM: if(bytes_read == 0) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; return false; } bytes -= bytes_read; buffer += bytes_read; break; - case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT: - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR; + case OggFLAC__STREAM_ENCODER_READ_STATUS_ABORT: + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + case OggFLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED: return false; default: /* double protection: */ FLAC__ASSERT(0); - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR; + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; return false; } } @@ -88,11 +90,12 @@ void simple_ogg_page__clear(ogg_page *page) simple_ogg_page__init(page); } -FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data) +FLAC__bool simple_ogg_page__get_at(OggFLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, OggFLAC__StreamEncoderReadCallback read_callback, void *client_data) { static const unsigned OGG_HEADER_FIXED_PORTION_LEN = 27; static const unsigned OGG_MAX_HEADER_LEN = 27/*OGG_HEADER_FIXED_PORTION_LEN*/ + 255; FLAC__byte crc[4]; + FLAC__StreamEncoderSeekStatus seek_status; FLAC__ASSERT(page->header == 0); FLAC__ASSERT(page->header_len == 0); @@ -100,14 +103,17 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC FLAC__ASSERT(page->body_len == 0); /* move the stream pointer to the supposed beginning of the page */ - if(seek_callback(encoder, position, client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR; + if(0 == seek_callback) + return false; + if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) { + if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR) + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; return false; } /* allocate space for the page header */ if(0 == (page->header = (unsigned char *)malloc(OGG_MAX_HEADER_LEN))) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + encoder->protected_->state = OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; return false; } @@ -125,7 +131,7 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC memcmp(page->header+6, "\0\0\0\0\0\0\0\0", 8) || /* granulepos is non-zero */ page->header[26] == 0 /* packet is 0-size */ ) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; return false; } @@ -139,7 +145,7 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC /* check to see that it specifies a single packet */ for(i = 0; i < (unsigned)page->header[26] - 1; i++) { if(page->header[i + OGG_HEADER_FIXED_PORTION_LEN] != 255) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; return false; } } @@ -149,7 +155,7 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC /* allocate space for the page body */ if(0 == (page->body = (unsigned char *)malloc(page->body_len))) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + encoder->protected_->state = OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; return false; } @@ -161,31 +167,36 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC memcpy(crc, page->header+22, 4); ogg_page_checksum_set(page); if(memcmp(crc, page->header+22, 4)) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; return false; } return true; } -FLAC__bool simple_ogg_page__set_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderWriteCallback write_callback, void *client_data) +FLAC__bool simple_ogg_page__set_at(OggFLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data) { + FLAC__StreamEncoderSeekStatus seek_status; + FLAC__ASSERT(page->header != 0); FLAC__ASSERT(page->header_len != 0); FLAC__ASSERT(page->body != 0); FLAC__ASSERT(page->body_len != 0); /* move the stream pointer to the supposed beginning of the page */ - if(seek_callback(encoder, position, client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR; + if(0 == seek_callback) + return false; + if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) { + if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR) + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; return false; } ogg_page_checksum_set(page); /* re-write the page */ - if(write_callback(encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR; + if(write_callback((FLAC__StreamEncoder*)encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; return false; } diff --git a/src/libOggFLAC/seekable_stream_decoder.c b/src/libOggFLAC/seekable_stream_decoder.c deleted file mode 100644 index 9721ef88..00000000 --- a/src/libOggFLAC/seekable_stream_decoder.c +++ /dev/null @@ -1,982 +0,0 @@ -/* libOggFLAC - Free Lossless Audio Codec + Ogg library - * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if HAVE_CONFIG_H -# include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> /* for calloc() */ -#include <string.h> /* for memcpy()/memcmp() */ -#include "FLAC/assert.h" -#include "protected/seekable_stream_decoder.h" -#include "protected/stream_decoder.h" -#include "../libFLAC/include/private/float.h" /* @@@ ugly hack, but how else to do? we need to reuse the float formats but don't want to expose it */ -#include "../libFLAC/include/private/md5.h" /* @@@ ugly hack, but how else to do? we need to reuse the md5 code but don't want to expose it */ - -/*********************************************************************** - * - * Private class method prototypes - * - ***********************************************************************/ - -static void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder); -static FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); -static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); -static void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); -static void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); -static FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample); - -/*********************************************************************** - * - * Private class data - * - ***********************************************************************/ - -typedef struct OggFLAC__SeekableStreamDecoderPrivate { - OggFLAC__SeekableStreamDecoderReadCallback read_callback; - OggFLAC__SeekableStreamDecoderSeekCallback seek_callback; - OggFLAC__SeekableStreamDecoderTellCallback tell_callback; - OggFLAC__SeekableStreamDecoderLengthCallback length_callback; - OggFLAC__SeekableStreamDecoderEofCallback eof_callback; - OggFLAC__SeekableStreamDecoderWriteCallback write_callback; - OggFLAC__SeekableStreamDecoderMetadataCallback metadata_callback; - OggFLAC__SeekableStreamDecoderErrorCallback error_callback; - void *client_data; - OggFLAC__StreamDecoder *stream_decoder; - FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */ - struct FLAC__MD5Context md5context; - FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */ - FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */ - /* the rest of these are only used for seeking: */ - FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */ - const FLAC__StreamMetadata_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */ - /* Since we always want to see the STREAMINFO and SEEK_TABLE blocks at this level, we need some extra flags to keep track of whether they should be passed on up through the metadata_callback */ - FLAC__bool ignore_stream_info_block; - FLAC__bool ignore_seek_table_block; - FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */ - FLAC__uint64 target_sample; - FLAC__bool got_a_frame; /* hack needed in seek routine to check when process_single() actually writes a frame */ -} OggFLAC__SeekableStreamDecoderPrivate; - -/*********************************************************************** - * - * Public static class data - * - ***********************************************************************/ - -OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderStateString[] = { - "OggFLAC__SEEKABLE_STREAM_DECODER_OK", - "OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING", - "OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM", - "OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR", - "OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR", - "OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR", - "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR", - "OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED", - "OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK", - "OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED" -}; - -OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderReadStatusString[] = { - "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK", - "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR" -}; - -OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderSeekStatusString[] = { - "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK", - "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR" -}; - -OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderTellStatusString[] = { - "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK", - "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR" -}; - -OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderLengthStatusString[] = { - "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK", - "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR" -}; - - -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new() -{ - OggFLAC__SeekableStreamDecoder *decoder; - - FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ - - decoder = (OggFLAC__SeekableStreamDecoder*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoder)); - if(decoder == 0) { - return 0; - } - - decoder->protected_ = (OggFLAC__SeekableStreamDecoderProtected*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderProtected)); - if(decoder->protected_ == 0) { - free(decoder); - return 0; - } - - decoder->private_ = (OggFLAC__SeekableStreamDecoderPrivate*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderPrivate)); - if(decoder->private_ == 0) { - free(decoder->protected_); - free(decoder); - return 0; - } - - decoder->private_->stream_decoder = OggFLAC__stream_decoder_new(); - if(0 == decoder->private_->stream_decoder) { - free(decoder->private_); - free(decoder->protected_); - free(decoder); - return 0; - } - - set_defaults_(decoder); - - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED; - - return decoder; -} - -OggFLAC_API void OggFLAC__seekable_stream_decoder_delete(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->private_->stream_decoder); - - (void)OggFLAC__seekable_stream_decoder_finish(decoder); - - OggFLAC__stream_decoder_delete(decoder->private_->stream_decoder); - - free(decoder->private_); - free(decoder->protected_); - free(decoder); -} - -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - -OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_init(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED; - - if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback) - return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK; - - if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback) - return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK; - - decoder->private_->seek_table = 0; - - decoder->private_->do_md5_checking = decoder->protected_->md5_checking; - - /* We initialize the FLAC__MD5Context even though we may never use it. This - * is because md5 checking may be turned on to start and then turned off if - * a seek occurs. So we always init the context here and finalize it in - * OggFLAC__seekable_stream_decoder_finish() to make sure things are always - * cleaned up properly. - */ - FLAC__MD5Init(&decoder->private_->md5context); - - OggFLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_); - OggFLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_); - OggFLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_); - OggFLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_); - OggFLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder); - - /* We always want to see these blocks. Whether or not we pass them up - * through the metadata callback will be determined by flags set in our - * implementation of ..._set_metadata_respond/ignore...() - */ - OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO); - OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE); - - if(OggFLAC__stream_decoder_init(decoder->private_->stream_decoder) != OggFLAC__STREAM_DECODER_OK) - return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - - return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__bool md5_failed = false; - - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - - if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return true; - - FLAC__ASSERT(0 != decoder->private_->stream_decoder); - - /* see the comment in OggFLAC__seekable_stream_decoder_init() as to why we - * always call FLAC__MD5Final() - */ - FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context); - - OggFLAC__stream_decoder_finish(decoder->private_->stream_decoder); - - if(decoder->private_->do_md5_checking) { - if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16)) - md5_failed = true; - } - - set_defaults_(decoder); - - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED; - - return !md5_failed; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_md5_checking(OggFLAC__SeekableStreamDecoder *decoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->protected_->md5_checking = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_read_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderReadCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->read_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_seek_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderSeekCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->seek_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_tell_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderTellCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->tell_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_length_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderLengthCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->length_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_eof_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderEofCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->eof_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_write_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderWriteCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->write_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderMetadataCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->metadata_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_error_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderErrorCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->error_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_client_data(OggFLAC__SeekableStreamDecoder *decoder, void *value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->client_data = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_serial_number(OggFLAC__SeekableStreamDecoder *decoder, long value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - OggFLAC__stream_decoder_set_serial_number(decoder->private_->stream_decoder, value); - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->stream_decoder); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - if(type == FLAC__METADATA_TYPE_STREAMINFO) - decoder->private_->ignore_stream_info_block = false; - else if(type == FLAC__METADATA_TYPE_SEEKTABLE) - decoder->private_->ignore_seek_table_block = false; - return OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4]) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->stream_decoder); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - return OggFLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->stream_decoder); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->ignore_stream_info_block = false; - decoder->private_->ignore_seek_table_block = false; - return OggFLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->stream_decoder); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - if(type == FLAC__METADATA_TYPE_STREAMINFO) { - decoder->private_->ignore_stream_info_block = true; - return true; - } - else if(type == FLAC__METADATA_TYPE_SEEKTABLE) { - decoder->private_->ignore_seek_table_block = true; - return true; - } - else - return OggFLAC__stream_decoder_set_metadata_ignore(decoder->private_->stream_decoder, type); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4]) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->stream_decoder); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - return OggFLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->stream_decoder, id); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - FLAC__ASSERT(0 != decoder->private_->stream_decoder); - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->ignore_stream_info_block = true; - decoder->private_->ignore_seek_table_block = true; - return - OggFLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->stream_decoder) && - OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO) && - OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE); -} - -OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->state; -} - -OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__stream_decoder_get_state(decoder->private_->stream_decoder); -} - -OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->private_->stream_decoder); -} - -OggFLAC_API const char *OggFLAC__seekable_stream_decoder_get_resolved_state_string(const OggFLAC__SeekableStreamDecoder *decoder) -{ - if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) - return OggFLAC__SeekableStreamDecoderStateString[decoder->protected_->state]; - else - return OggFLAC__stream_decoder_get_resolved_state_string(decoder->private_->stream_decoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_md5_checking(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->protected_); - return decoder->protected_->md5_checking; -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_channels(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__stream_decoder_get_channels(decoder->private_->stream_decoder); -} - -OggFLAC_API FLAC__ChannelAssignment OggFLAC__seekable_stream_decoder_get_channel_assignment(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__stream_decoder_get_channel_assignment(decoder->private_->stream_decoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_bits_per_sample(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__stream_decoder_get_bits_per_sample(decoder->private_->stream_decoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__stream_decoder_get_sample_rate(decoder->private_->stream_decoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - return OggFLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - - decoder->private_->do_md5_checking = false; - - if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - return false; - } - - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK; - - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_reset(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - - if(!OggFLAC__seekable_stream_decoder_flush(decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - return false; - } - - if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - return false; - } - - decoder->private_->seek_table = 0; - - decoder->private_->do_md5_checking = decoder->protected_->md5_checking; - - /* We initialize the FLAC__MD5Context even though we may never use it. This - * is because md5 checking may be turned on to start and then turned off if - * a seek occurs. So we always init the context here and finalize it in - * OggFLAC__seekable_stream_decoder_finish() to make sure things are always - * cleaned up properly. - */ - FLAC__MD5Init(&decoder->private_->md5context); - - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK; - - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__bool ret; - FLAC__ASSERT(0 != decoder); - - if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; - - if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) - return true; - - FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK); - - ret = OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder); - if(!ret) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - - return ret; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__bool ret; - FLAC__ASSERT(0 != decoder); - - if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; - - if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) - return true; - - FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK); - - ret = OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder); - if(!ret) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - - return ret; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_stream(OggFLAC__SeekableStreamDecoder *decoder) -{ - FLAC__bool ret; - FLAC__ASSERT(0 != decoder); - - if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; - - if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) - return true; - - FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK); - - ret = OggFLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder); - if(!ret) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - - return ret; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_seek_absolute(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample) -{ - FLAC__uint64 length; - - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM); - - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING; - - /* turn off md5 checking if a seek is attempted */ - decoder->private_->do_md5_checking = false; - - if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - return false; - } - /* get the file length */ - if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; - return false; - } - /* rewind */ - if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; - return false; - } - if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - return false; - } - if(decoder->private_->stream_info.total_samples > 0 && sample >= decoder->private_->stream_info.total_samples) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; - return false; - } - - return seek_to_absolute_sample_(decoder, length, sample); -} - -/*********************************************************************** - * - * Private class methods - * - ***********************************************************************/ - -void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder) -{ - decoder->private_->read_callback = 0; - decoder->private_->seek_callback = 0; - decoder->private_->tell_callback = 0; - decoder->private_->length_callback = 0; - decoder->private_->eof_callback = 0; - decoder->private_->write_callback = 0; - decoder->private_->metadata_callback = 0; - decoder->private_->error_callback = 0; - decoder->private_->client_data = 0; - /* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */ - decoder->private_->ignore_stream_info_block = false; - decoder->private_->ignore_seek_table_block = true; - - decoder->protected_->md5_checking = false; -} - -FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data; - (void)decoder; - if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) { - *bytes = 0; -#if 0 - /*@@@@@@ we used to do this: */ - seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; - /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */ -#endif - return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - } - else if(*bytes > 0) { - if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) { - seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR; - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - } - if(*bytes == 0) { - if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) { -#if 0 - /*@@@@@@ we used to do this: */ - seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; - /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */ -#endif - return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - } - else - return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; - } - else { - return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; - } - } - else - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */ -} - -FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) -{ - OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data; - (void)decoder; - - if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) { - FLAC__uint64 this_frame_sample = frame->header.number.sample_number; - FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize; - FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample; - - FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); - - seekable_stream_decoder->private_->got_a_frame = true; - seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */ - if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */ - unsigned delta = (unsigned)(target_sample - this_frame_sample); - /* kick out of seek mode */ - seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK; - /* shift out the samples before target_sample */ - if(delta > 0) { - unsigned channel; - const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS]; - for(channel = 0; channel < frame->header.channels; channel++) - newbuffer[channel] = buffer[channel] + delta; - seekable_stream_decoder->private_->last_frame.header.blocksize -= delta; - seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta; - /* write the relevant samples */ - return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data); - } - else { - /* write the relevant samples */ - return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data); - } - } - else { - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; - } - } - else { - if(seekable_stream_decoder->private_->do_md5_checking) { - if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8)) - return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - } - return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data); - } -} - -void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data; - (void)decoder; - - if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { - seekable_stream_decoder->private_->stream_info = metadata->data.stream_info; - /* save the MD5 signature for comparison later */ - memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16); - if(0 == memcmp(seekable_stream_decoder->private_->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) - seekable_stream_decoder->private_->do_md5_checking = false; - } - else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) { - seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table; - } - - if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) { - FLAC__bool ignore_block = false; - if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block) - ignore_block = true; - else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block) - ignore_block = true; - if(!ignore_block) - seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data); - } -} - -void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data; - (void)decoder; - - if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) - seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data); -} - -FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample) -{ - FLAC__uint64 left_pos = 0, right_pos = stream_length; - FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples; - FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */ - FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */ - FLAC__bool did_a_seek; - unsigned iteration = 0; - - /* In the first iterations, we will calculate the target byte position - * by the distance from the target sample to left_sample and - * right_sample (let's call it "proportional search"). After that, we - * will switch to binary search. - */ - unsigned BINARY_SEARCH_AFTER_ITERATION = 2; - - /* We will switch to a linear search once our current sample is less - * that this number of samples ahead of the target sample - */ - static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2; - - /* If the total number of samples is unknown, use a large value and - * increase 'iteration' to force binary search immediately. - */ - if(right_sample == 0) { - right_sample = (FLAC__uint64)(-1); - BINARY_SEARCH_AFTER_ITERATION = 0; - } - - decoder->private_->target_sample = target_sample; - for( ; ; iteration++) { - if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) { - if (iteration >= BINARY_SEARCH_AFTER_ITERATION) { - pos = (right_pos + left_pos) / 2; - } - else { -#ifndef FLAC__INTEGER_ONLY_LIBRARY -#if defined _MSC_VER || defined __MINGW32__ - /* with MSVC you have to spoon feed it the casting */ - pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos)); -#else - pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos)); -#endif -#else - /* a little less accurate: */ - if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff)) - pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample)); - else /* @@@ WATCHOUT, ~2TB limit */ - pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16)); -#endif - /* @@@ TODO: might want to limit pos to some distance - * before EOF, to make sure we land before the last frame, - * thereby getting a this_fram_sample and so having a better - * estimate. this would also mostly (or totally if we could - * be sure to land before the last frame) avoid the - * end-of-stream case we have to check later. - */ - } - - /* physical seek */ - if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; - return false; - } - if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; - return false; - } - did_a_seek = true; - } - else - did_a_seek = false; - - decoder->private_->got_a_frame = false; - if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; - return false; - } - if(!decoder->private_->got_a_frame) { - if(did_a_seek) { - /* this can happen if we seek to a point after the last frame; we drop - * to binary search right away in this case to avoid any wasted - * iterations of proportional search. - */ - right_pos = pos; - BINARY_SEARCH_AFTER_ITERATION = 0; - } - else { - /* this can probably only happen if total_samples is unknown and the - * target_sample is past the end of the stream - */ - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; - return false; - } - } - /* our write callback will change the state when it gets to the target frame */ - else if( - decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING && - decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM - ) { - break; - } - else { - this_frame_sample = decoder->private_->last_frame.header.number.sample_number; - FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); - - if (did_a_seek) { - if (this_frame_sample <= target_sample) { - /* The 'equal' case should not happen, since - * OggFLAC__stream_decoder_process_single() - * should recognize that it has hit the - * target sample and we would exit through - * the 'break' above. - */ - FLAC__ASSERT(this_frame_sample != target_sample); - - left_sample = this_frame_sample; - /* sanity check to avoid infinite loop */ - if (left_pos == pos) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; - return false; - } - left_pos = pos; - } - else if(this_frame_sample > target_sample) { - right_sample = this_frame_sample; - /* sanity check to avoid infinite loop */ - if (right_pos == pos) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; - return false; - } - right_pos = pos; - } - } - } - } - - return true; -} diff --git a/src/libOggFLAC/seekable_stream_encoder.c b/src/libOggFLAC/seekable_stream_encoder.c deleted file mode 100644 index b222905e..00000000 --- a/src/libOggFLAC/seekable_stream_encoder.c +++ /dev/null @@ -1,1078 +0,0 @@ -/* libOggFLAC - Free Lossless Audio Codec + Ogg library - * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if HAVE_CONFIG_H -# include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> /* for calloc() */ -#include <string.h> /* for memcpy() */ -#include "FLAC/assert.h" -#include "OggFLAC/seekable_stream_encoder.h" -#include "protected/seekable_stream_encoder.h" -#include "private/ogg_helper.h" - -#ifdef max -#undef max -#endif -#define max(a,b) ((a)>(b)?(a):(b)) - -/*********************************************************************** - * - * Private class method prototypes - * - ***********************************************************************/ - -/* unpublished debug routines */ -extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); -extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); -extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); - -static void set_defaults_(OggFLAC__SeekableStreamEncoder *encoder); -static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); -static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); - - -/*********************************************************************** - * - * Private class data - * - ***********************************************************************/ - -typedef struct OggFLAC__SeekableStreamEncoderPrivate { - OggFLAC__SeekableStreamEncoderReadCallback read_callback; - OggFLAC__SeekableStreamEncoderSeekCallback seek_callback; - OggFLAC__SeekableStreamEncoderTellCallback tell_callback; - OggFLAC__SeekableStreamEncoderWriteCallback write_callback; - void *client_data; - FLAC__StreamEncoder *FLAC_stream_encoder; - FLAC__StreamMetadata_SeekTable *seek_table; - /* internal vars (all the above are class settings) */ - unsigned first_seekpoint_to_check; - FLAC__uint64 samples_written; -} OggFLAC__SeekableStreamEncoderPrivate; - - -/*********************************************************************** - * - * Public static class data - * - ***********************************************************************/ - -OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderStateString[] = { - "OggFLAC__SEEKABLE_STREAM_ENCODER_OK", - "OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR", - "OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR", - "OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR", - "OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR", - "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR", - "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR", - "OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR", - "OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR", - "OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED", - "OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK", - "OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE", - "OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED" -}; - -OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderReadStatusString[] = { - "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE", - "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM", - "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT" -}; - - -/*********************************************************************** - * - * Class constructor/destructor - * - */ -OggFLAC_API OggFLAC__SeekableStreamEncoder *OggFLAC__seekable_stream_encoder_new() -{ - OggFLAC__SeekableStreamEncoder *encoder; - - encoder = (OggFLAC__SeekableStreamEncoder*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoder)); - if(encoder == 0) { - return 0; - } - - encoder->protected_ = (OggFLAC__SeekableStreamEncoderProtected*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoderProtected)); - if(encoder->protected_ == 0) { - free(encoder); - return 0; - } - - encoder->private_ = (OggFLAC__SeekableStreamEncoderPrivate*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoderPrivate)); - if(encoder->private_ == 0) { - free(encoder->protected_); - free(encoder); - return 0; - } - - encoder->private_->FLAC_stream_encoder = FLAC__stream_encoder_new(); - if(0 == encoder->private_->FLAC_stream_encoder) { - free(encoder->private_); - free(encoder->protected_); - free(encoder); - return 0; - } - - set_defaults_(encoder); - - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED; - - return encoder; -} - -OggFLAC_API void OggFLAC__seekable_stream_encoder_delete(OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - - (void)OggFLAC__seekable_stream_encoder_finish(encoder); - - FLAC__stream_encoder_delete(encoder->private_->FLAC_stream_encoder); - - free(encoder->private_); - free(encoder->protected_); - free(encoder); -} - - -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - -OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_init(OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED; - - if(0 == encoder->private_->seek_callback || 0 == encoder->private_->tell_callback || 0 == encoder->private_->write_callback) - return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK; - - if(!OggFLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect)) - return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; - - if(0 != encoder->private_->seek_table && !FLAC__format_seektable_is_legal(encoder->private_->seek_table)) - return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE; - - /* - * These must be done before we init the stream encoder because that - * calls the write_callback, which uses these values. - */ - encoder->private_->first_seekpoint_to_check = 0; - encoder->private_->samples_written = 0; - encoder->protected_->streaminfo_offset = 0; - encoder->protected_->seektable_offset = 0; - encoder->protected_->audio_offset = 0; - - FLAC__stream_encoder_set_write_callback(encoder->private_->FLAC_stream_encoder, write_callback_); - FLAC__stream_encoder_set_metadata_callback(encoder->private_->FLAC_stream_encoder, metadata_callback_); - FLAC__stream_encoder_set_client_data(encoder->private_->FLAC_stream_encoder, encoder); - - if(FLAC__stream_encoder_init(encoder->private_->FLAC_stream_encoder) != FLAC__STREAM_ENCODER_OK) - return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR; - - /* - * Initializing the stream encoder writes all the metadata, so we - * save the stream offset now. - */ - if(encoder->private_->tell_callback(encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK) - return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR; - - return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OK; -} - -OggFLAC_API void OggFLAC__seekable_stream_encoder_finish(OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - - if(encoder->protected_->state == OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return; - - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - - FLAC__stream_encoder_finish(encoder->private_->FLAC_stream_encoder); - - OggFLAC__ogg_encoder_aspect_finish(&encoder->protected_->ogg_encoder_aspect); - - set_defaults_(encoder); - - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_serial_number(OggFLAC__SeekableStreamEncoder *encoder, long value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - OggFLAC__ogg_encoder_aspect_set_serial_number(&encoder->protected_->ogg_encoder_aspect, value); - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_verify(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_verify(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_streamable_subset(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_streamable_subset(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_channels(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_channels(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_bits_per_sample(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_sample_rate(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_sample_rate(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_blocksize(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_apodization(OggFLAC__SeekableStreamEncoder *encoder, const char *specification) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_apodization(encoder->private_->FLAC_stream_encoder, specification); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_lpc_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_escape_coding(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(OggFLAC__SeekableStreamEncoder *encoder, unsigned value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_total_samples_estimate(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - /* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */ - if(0 != metadata && num_blocks > 1) { - unsigned i; - for(i = 1; i < num_blocks; i++) { - if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { - FLAC__StreamMetadata *vc = metadata[i]; - for( ; i > 0; i--) - metadata[i] = metadata[i-1]; - metadata[0] = vc; - break; - } - } - } - if(0 != metadata && num_blocks > 0) { - unsigned i; - for(i = 0; i < num_blocks; i++) { - /* keep track of any SEEKTABLE block */ - if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) { - encoder->private_->seek_table = &metadata[i]->data.seek_table; - break; /* take only the first one */ - } - } - } - if(!OggFLAC__ogg_encoder_aspect_set_num_metadata(&encoder->protected_->ogg_encoder_aspect, num_blocks)) - return false; - return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_read_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderReadCallback value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != value); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - encoder->private_->read_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_seek_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderSeekCallback value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != value); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - encoder->private_->seek_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_tell_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderTellCallback value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != value); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - encoder->private_->tell_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_write_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderWriteCallback value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != value); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - encoder->private_->write_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_client_data(OggFLAC__SeekableStreamEncoder *encoder, void *value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - encoder->private_->client_data = value; - return true; -} - -/* - * These three functions are not static, but not publically exposed in - * include/FLAC/ either. They are used by the test suite. - */ -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_constant_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_disable_constant_subframes(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_fixed_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_disable_fixed_subframes(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) - return false; - return FLAC__stream_encoder_disable_verbatim_subframes(encoder->private_->FLAC_stream_encoder, value); -} - -OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_get_state(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - return encoder->protected_->state; -} - -OggFLAC_API FLAC__StreamEncoderState OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_state(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_encoder_get_verify_decoder_state(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API const char *OggFLAC__seekable_stream_encoder_get_resolved_state_string(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) - return OggFLAC__SeekableStreamEncoderStateString[encoder->protected_->state]; - else - return FLAC__stream_encoder_get_resolved_state_string(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API void OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - FLAC__stream_encoder_get_verify_decoder_error_stats(encoder->private_->FLAC_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_verify(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_verify(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_streamable_subset(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_streamable_subset(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_channels(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_channels(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_bits_per_sample(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_sample_rate(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_sample_rate(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_blocksize(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_max_lpc_order(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_escape_coding(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__uint64 OggFLAC__seekable_stream_encoder_get_total_samples_estimate(const OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - return FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder); -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_process(OggFLAC__SeekableStreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(!FLAC__stream_encoder_process(encoder->private_->FLAC_stream_encoder, buffer, samples)) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR; - return false; - } - else - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_process_interleaved(OggFLAC__SeekableStreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - if(!FLAC__stream_encoder_process_interleaved(encoder->private_->FLAC_stream_encoder, buffer, samples)) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR; - return false; - } - else - return true; -} - -/*********************************************************************** - * - * Private class methods - * - ***********************************************************************/ - -void set_defaults_(OggFLAC__SeekableStreamEncoder *encoder) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - - encoder->private_->seek_callback = 0; - encoder->private_->tell_callback = 0; - encoder->private_->write_callback = 0; - encoder->private_->client_data = 0; - - encoder->private_->seek_table = 0; - - OggFLAC__ogg_encoder_aspect_set_defaults(&encoder->protected_->ogg_encoder_aspect); -} - -FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) -{ - OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data; - FLAC__StreamEncoderWriteStatus status; - FLAC__uint64 output_position; - - (void)unused; /* silence compiler warning about unused parameter */ - FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused); - - if(encoder->private_->tell_callback(encoder, &output_position, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK) - return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR; - - /* - * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets. - */ - if(samples == 0) { - FLAC__MetadataType type = (buffer[0] & 0x7f); - if(type == FLAC__METADATA_TYPE_STREAMINFO) - encoder->protected_->streaminfo_offset = output_position; - else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0) - encoder->protected_->seektable_offset = output_position; - } - - /* - * Mark the current seek point if hit (if audio_offset == 0 that - * means we're still writing metadata and haven't hit the first - * frame yet) - */ - if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) { - const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder); - const FLAC__uint64 frame_first_sample = encoder->private_->samples_written; - const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1; - FLAC__uint64 test_sample; - unsigned i; - for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) { - test_sample = encoder->private_->seek_table->points[i].sample_number; - if(test_sample > frame_last_sample) { - break; - } - else if(test_sample >= frame_first_sample) { - encoder->private_->seek_table->points[i].sample_number = frame_first_sample; - encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset; - encoder->private_->seek_table->points[i].frame_samples = blocksize; - encoder->private_->first_seekpoint_to_check++; - /* DO NOT: "break;" and here's why: - * The seektable template may contain more than one target - * sample for any given frame; we will keep looping, generating - * duplicate seekpoints for them, and we'll clean it up later, - * just before writing the seektable back to the metadata. - */ - } - else { - encoder->private_->first_seekpoint_to_check++; - } - } - } - - status = OggFLAC__ogg_encoder_aspect_write_callback_wrapper(&encoder->protected_->ogg_encoder_aspect, FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder), buffer, bytes, samples, current_frame, (OggFLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback, encoder, encoder->private_->client_data); - - if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { - encoder->private_->samples_written += samples; - } - else - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR; - - return status; -} - -void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMetadata *metadata, void *client_data) -{ - OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data; - FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)]; - const FLAC__uint64 samples = metadata->data.stream_info.total_samples; - const unsigned min_framesize = metadata->data.stream_info.min_framesize; - const unsigned max_framesize = metadata->data.stream_info.max_framesize; - ogg_page page; - - FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO); - - /* We get called by the stream encoder when the encoding process - * has finished so that we can update the STREAMINFO and SEEKTABLE - * blocks. - */ - - (void)unused; /* silence compiler warning about unused parameter */ - FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused); - - /*@@@ reopen callback here? The docs currently require user to open files in update mode from the start */ - - /* All this is based on intimate knowledge of the stream header - * layout, but a change to the header format that would break this - * would also break all streams encoded in the previous format. - */ - - /* - * Write STREAMINFO stats - */ - simple_ogg_page__init(&page); - if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) { - simple_ogg_page__clear(&page); - return; /* state already set */ - } - /* - * MD5 signature - */ - { - const unsigned md5_offset = - FLAC__STREAM_METADATA_HEADER_LENGTH + - ( - FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN + - FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN - ) / 8; - - if(md5_offset + 16 > (unsigned)page.body_len) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; - simple_ogg_page__clear(&page); - return; - } - memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16); - } - /* - * total samples - */ - { - const unsigned total_samples_byte_offset = - FLAC__STREAM_METADATA_HEADER_LENGTH + - ( - FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN + - FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN - - 4 - ) / 8; - - if(total_samples_byte_offset + 5 > (unsigned)page.body_len) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; - simple_ogg_page__clear(&page); - return; - } - b[0] = (FLAC__byte)page.body[total_samples_byte_offset] & 0xF0; - b[0] |= (FLAC__byte)((samples >> 32) & 0x0F); - b[1] = (FLAC__byte)((samples >> 24) & 0xFF); - b[2] = (FLAC__byte)((samples >> 16) & 0xFF); - b[3] = (FLAC__byte)((samples >> 8) & 0xFF); - b[4] = (FLAC__byte)(samples & 0xFF); - memcpy(page.body + total_samples_byte_offset, b, 5); - } - /* - * min/max framesize - */ - { - const unsigned min_framesize_offset = - FLAC__STREAM_METADATA_HEADER_LENGTH + - ( - FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + - FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN - ) / 8; - - if(min_framesize_offset + 6 > (unsigned)page.body_len) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; - simple_ogg_page__clear(&page); - return; - } - b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF); - b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF); - b[2] = (FLAC__byte)(min_framesize & 0xFF); - b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF); - b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF); - b[5] = (FLAC__byte)(max_framesize & 0xFF); - memcpy(page.body + min_framesize_offset, b, 6); - } - if(!simple_ogg_page__set_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) { - simple_ogg_page__clear(&page); - return; /* state already set */ - } - simple_ogg_page__clear(&page); - - /* - * Write seektable - */ - if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) { - unsigned i; - FLAC__byte *p; - - FLAC__format_seektable_sort(encoder->private_->seek_table); - - FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table)); - - simple_ogg_page__init(&page); - if(!simple_ogg_page__get_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) { - simple_ogg_page__clear(&page); - return; /* state already set */ - } - - if(FLAC__STREAM_METADATA_HEADER_LENGTH + (18*encoder->private_->seek_table->num_points) > (unsigned)page.body_len) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR; - simple_ogg_page__clear(&page); - return; - } - - for(i = 0, p = page.body + FLAC__STREAM_METADATA_HEADER_LENGTH; i < encoder->private_->seek_table->num_points; i++, p += 18) { - FLAC__uint64 xx; - unsigned x; - xx = encoder->private_->seek_table->points[i].sample_number; - b[7] = (FLAC__byte)xx; xx >>= 8; - b[6] = (FLAC__byte)xx; xx >>= 8; - b[5] = (FLAC__byte)xx; xx >>= 8; - b[4] = (FLAC__byte)xx; xx >>= 8; - b[3] = (FLAC__byte)xx; xx >>= 8; - b[2] = (FLAC__byte)xx; xx >>= 8; - b[1] = (FLAC__byte)xx; xx >>= 8; - b[0] = (FLAC__byte)xx; xx >>= 8; - xx = encoder->private_->seek_table->points[i].stream_offset; - b[15] = (FLAC__byte)xx; xx >>= 8; - b[14] = (FLAC__byte)xx; xx >>= 8; - b[13] = (FLAC__byte)xx; xx >>= 8; - b[12] = (FLAC__byte)xx; xx >>= 8; - b[11] = (FLAC__byte)xx; xx >>= 8; - b[10] = (FLAC__byte)xx; xx >>= 8; - b[9] = (FLAC__byte)xx; xx >>= 8; - b[8] = (FLAC__byte)xx; xx >>= 8; - x = encoder->private_->seek_table->points[i].frame_samples; - b[17] = (FLAC__byte)x; x >>= 8; - b[16] = (FLAC__byte)x; x >>= 8; - if(encoder->private_->write_callback(encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { - encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR; - simple_ogg_page__clear(&page); - return; - } - memcpy(p, b, 18); - } - - if(!simple_ogg_page__set_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) { - simple_ogg_page__clear(&page); - return; /* state already set */ - } - simple_ogg_page__clear(&page); - } -} diff --git a/src/libOggFLAC/stream_decoder.c b/src/libOggFLAC/stream_decoder.c index 21557c6c..aec61463 100644 --- a/src/libOggFLAC/stream_decoder.c +++ b/src/libOggFLAC/stream_decoder.c @@ -33,9 +33,26 @@ # include <config.h> #endif +#if defined _MSC_VER || defined __MINGW32__ +#include <io.h> /* for _setmode() */ +#include <fcntl.h> /* for _O_BINARY */ +#endif +#if defined __CYGWIN__ || defined __EMX__ +#include <io.h> /* for setmode(), O_BINARY */ +#include <fcntl.h> /* for _O_BINARY */ +#endif +#include <stdio.h> #include <stdlib.h> /* for calloc() */ +#include <sys/stat.h> /* for stat() */ +#include <sys/types.h> /* for off_t */ +#if defined _MSC_VER || defined __MINGW32__ +/*@@@ [2G limit] hacks for MSVC6 */ +#define fseeko fseek +#define ftello ftell +#endif #include "FLAC/assert.h" #include "protected/stream_decoder.h" +#include "../libFLAC/include/private/float.h" /* @@@ ugly hack, but how else to do? we need to reuse the float formats but don't want to expose it */ /*********************************************************************** * @@ -44,11 +61,19 @@ ***********************************************************************/ static void set_defaults_(OggFLAC__StreamDecoder *decoder); -static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +static FILE *get_binary_stdin_(); +static FLAC__StreamDecoderReadStatus read_callback2_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +static FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +static OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); -static OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +static FLAC__bool seek_to_absolute_sample_(OggFLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample); +static FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +static FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); +static FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); +static FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); +static FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data); /*********************************************************************** @@ -58,12 +83,21 @@ static OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void ***********************************************************************/ typedef struct OggFLAC__StreamDecoderPrivate { - OggFLAC__StreamDecoderReadCallback read_callback; - OggFLAC__StreamDecoderWriteCallback write_callback; - OggFLAC__StreamDecoderMetadataCallback metadata_callback; - OggFLAC__StreamDecoderErrorCallback error_callback; + FLAC__StreamDecoderReadCallback read_callback; + FLAC__StreamDecoderSeekCallback seek_callback; + FLAC__StreamDecoderTellCallback tell_callback; + FLAC__StreamDecoderLengthCallback length_callback; + FLAC__StreamDecoderEofCallback eof_callback; + FLAC__StreamDecoderWriteCallback write_callback; + FLAC__StreamDecoderMetadataCallback metadata_callback; + FLAC__StreamDecoderErrorCallback error_callback; void *client_data; - FLAC__StreamDecoder *FLAC_stream_decoder; + FILE *file; /* only used if OggFLAC__stream_decoder_init_file()/OggFLAC__stream_decoder_init_file() called, else NULL */ + /* the rest of these are only used for seeking: */ + FLAC__bool is_seeking; + FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */ + FLAC__uint64 target_sample; + FLAC__bool got_a_frame; /* hack needed in seek routine to check when process_single() actually writes a frame */ } OggFLAC__StreamDecoderPrivate; /*********************************************************************** @@ -76,12 +110,12 @@ OggFLAC_API const char * const OggFLAC__StreamDecoderStateString[] = { "OggFLAC__STREAM_DECODER_OK", "OggFLAC__STREAM_DECODER_END_OF_STREAM", "OggFLAC__STREAM_DECODER_OGG_ERROR", - "OggFLAC__STREAM_DECODER_READ_ERROR", "OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR", + "OggFLAC__STREAM_DECODER_SEEK_ERROR", + "OggFLAC__STREAM_DECODER_READ_ERROR", "OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR", - "OggFLAC__STREAM_DECODER_ALREADY_INITIALIZED", - "OggFLAC__STREAM_DECODER_INVALID_CALLBACK", "OggFLAC__STREAM_DECODER_UNINITIALIZED" + //@@@@@@ }; @@ -93,6 +127,9 @@ OggFLAC_API const char * const OggFLAC__StreamDecoderStateString[] = { OggFLAC_API OggFLAC__StreamDecoder *OggFLAC__stream_decoder_new() { OggFLAC__StreamDecoder *decoder; + FLAC__StreamDecoder *parent; + + FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ decoder = (OggFLAC__StreamDecoder*)calloc(1, sizeof(OggFLAC__StreamDecoder)); if(decoder == 0) { @@ -112,13 +149,16 @@ OggFLAC_API OggFLAC__StreamDecoder *OggFLAC__stream_decoder_new() return 0; } - decoder->private_->FLAC_stream_decoder = FLAC__stream_decoder_new(); - if(0 == decoder->private_->FLAC_stream_decoder) { + parent = FLAC__stream_decoder_new(); + if(0 == parent) { free(decoder->private_); free(decoder->protected_); free(decoder); return 0; } + decoder->super_ = *parent; + + decoder->private_->file = 0; set_defaults_(decoder); @@ -132,15 +172,15 @@ OggFLAC_API void OggFLAC__stream_decoder_delete(OggFLAC__StreamDecoder *decoder) FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->protected_); FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->private_->FLAC_stream_decoder); OggFLAC__stream_decoder_finish(decoder); - FLAC__stream_decoder_delete(decoder->private_->FLAC_stream_decoder); - free(decoder->private_); free(decoder->protected_); - free(decoder); + /* don't free(decoder) because FLAC__stream_decoder_delete() will do it */ + + /* call superclass destructor last */ + FLAC__stream_decoder_delete((FLAC__StreamDecoder*)decoder); } /*********************************************************************** @@ -149,104 +189,192 @@ OggFLAC_API void OggFLAC__stream_decoder_delete(OggFLAC__StreamDecoder *decoder) * ***********************************************************************/ -OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__stream_decoder_init(OggFLAC__StreamDecoder *decoder) +OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_stream( + OggFLAC__StreamDecoder *decoder, + FLAC__StreamDecoderReadCallback read_callback, + FLAC__StreamDecoderSeekCallback seek_callback, + FLAC__StreamDecoderTellCallback tell_callback, + FLAC__StreamDecoderLengthCallback length_callback, + FLAC__StreamDecoderEofCallback eof_callback, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) { FLAC__ASSERT(0 != decoder); if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) - return decoder->protected_->state = OggFLAC__STREAM_DECODER_ALREADY_INITIALIZED; + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; - if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback) - return decoder->protected_->state = OggFLAC__STREAM_DECODER_INVALID_CALLBACK; + if( + 0 == read_callback || + 0 == write_callback || + 0 == error_callback || + (seek_callback && (0 == tell_callback || 0 == length_callback || 0 == eof_callback)) + ) + return FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; if(!OggFLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect)) return decoder->protected_->state = OggFLAC__STREAM_DECODER_OGG_ERROR; - FLAC__stream_decoder_set_read_callback(decoder->private_->FLAC_stream_decoder, read_callback_); - FLAC__stream_decoder_set_write_callback(decoder->private_->FLAC_stream_decoder, write_callback_); - FLAC__stream_decoder_set_metadata_callback(decoder->private_->FLAC_stream_decoder, metadata_callback_); - FLAC__stream_decoder_set_error_callback(decoder->private_->FLAC_stream_decoder, error_callback_); - FLAC__stream_decoder_set_client_data(decoder->private_->FLAC_stream_decoder, decoder); + /* from here on, errors are fatal */ + + decoder->private_->read_callback = read_callback; + decoder->private_->seek_callback = seek_callback; + decoder->private_->tell_callback = tell_callback; + decoder->private_->length_callback = length_callback; + decoder->private_->eof_callback = eof_callback; + decoder->private_->write_callback = write_callback; + decoder->private_->metadata_callback = metadata_callback; + decoder->private_->error_callback = error_callback; + decoder->private_->client_data = client_data; + + decoder->private_->is_seeking = false; - if(FLAC__stream_decoder_init(decoder->private_->FLAC_stream_decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) + if(FLAC__stream_decoder_init_stream((FLAC__StreamDecoder*)decoder, read_callback_ogg_aspect_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, write_callback_, metadata_callback_, error_callback_, /*client_data=*/decoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK) \ return decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR; - return decoder->protected_->state = OggFLAC__STREAM_DECODER_OK; + decoder->protected_->state = OggFLAC__STREAM_DECODER_OK; + return FLAC__STREAM_DECODER_INIT_STATUS_OK; } -OggFLAC_API void OggFLAC__stream_decoder_finish(OggFLAC__StreamDecoder *decoder) +OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_FILE( + OggFLAC__StreamDecoder *decoder, + FILE *file, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) { FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT(0 != file); - if(decoder->protected_->state == OggFLAC__STREAM_DECODER_UNINITIALIZED) - return; + if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; - FLAC__ASSERT(0 != decoder->private_->FLAC_stream_decoder); + if(0 == write_callback || 0 == error_callback) + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; - FLAC__stream_decoder_finish(decoder->private_->FLAC_stream_decoder); + /* + * To make sure that our file does not go unclosed after an error, we + * must assign the FILE pointer before any further error can occur in + * this routine. + */ + if(file == stdin) + file = get_binary_stdin_(); /* just to be safe */ - OggFLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect); + decoder->private_->file = file; - set_defaults_(decoder); +#ifdef OLD_STAT_WAY //@@@@@@ + if(0 != decoder->private_->filename) { + free(decoder->private_->filename); + decoder->private_->filename = 0; + } + if(filename) { + if(0 == (decoder->private_->filename = strdup(filename))) { + decoder->protected_->state = OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR; + } + } +#endif - decoder->protected_->state = OggFLAC__STREAM_DECODER_UNINITIALIZED; + return OggFLAC__stream_decoder_init_stream( + decoder, + file_read_callback_, + decoder->private_->file == stdin? 0: file_seek_callback_, + decoder->private_->file == stdin? 0: file_tell_callback_,/*@@@@@@ might work for stdin*/ + decoder->private_->file == stdin? 0: file_length_callback_, + decoder->private_->file == stdin? 0: file_eof_callback_,/*@@@@@@ might work for stdin*/ + write_callback, + metadata_callback, + error_callback, + client_data + ); } -OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_read_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderReadCallback value) +OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_file( + OggFLAC__StreamDecoder *decoder, + const char *filename, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) { - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->read_callback = value; - return true; -} + FILE *file; -OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_write_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderWriteCallback value) -{ FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->write_callback = value; - return true; -} -OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderMetadataCallback value) -{ - FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->protected_); + /* + * To make sure that our file does not go unclosed after an error, we + * have to do the same entrance checks here that are later performed + * in OggFLAC__stream_decoder_init_FILE() before the FILE* is assigned. + */ if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->metadata_callback = value; - return true; + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; + + if(0 == write_callback || 0 == error_callback) + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; + + file = filename? fopen(filename, "rb") : stdin; + + if(0 == file) + return FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE; + +#ifdef OLD_STAT_WAY //@@@@@@ + if(0 != decoder->private_->filename) { + free(decoder->private_->filename); + decoder->private_->filename = 0; + } + if(filename) { + if(0 == (decoder->private_->filename = strdup(filename))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR; + } + } +#endif + + return OggFLAC__stream_decoder_init_FILE(decoder, file, write_callback, metadata_callback, error_callback, client_data); } -OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_error_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderErrorCallback value) +OggFLAC_API FLAC__bool OggFLAC__stream_decoder_finish(OggFLAC__StreamDecoder *decoder) { + FLAC__bool md5_ok; + FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); FLAC__ASSERT(0 != decoder->protected_); - if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) - return false; - decoder->private_->error_callback = value; - return true; + + if(decoder->protected_->state == OggFLAC__STREAM_DECODER_UNINITIALIZED) + return true; + + md5_ok = FLAC__stream_decoder_finish((FLAC__StreamDecoder*)decoder); + + OggFLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect); + + if(0 != decoder->private_->file && decoder->private_->file != stdin) { + fclose(decoder->private_->file); + decoder->private_->file = 0; + } + + decoder->private_->is_seeking = false; + + set_defaults_(decoder); + + decoder->protected_->state = OggFLAC__STREAM_DECODER_UNINITIALIZED; + + return md5_ok; } -OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_client_data(OggFLAC__StreamDecoder *decoder, void *value) +OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_md5_checking(OggFLAC__StreamDecoder *decoder, FLAC__bool value) { FLAC__ASSERT(0 != decoder); - FLAC__ASSERT(0 != decoder->private_); FLAC__ASSERT(0 != decoder->protected_); if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) return false; - decoder->private_->client_data = value; - return true; + return FLAC__stream_decoder_set_md5_checking((FLAC__StreamDecoder*)decoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_serial_number(OggFLAC__StreamDecoder *decoder, long value) @@ -267,7 +395,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond(OggFLAC__Str FLAC__ASSERT(0 != decoder->protected_); if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) return false; - return FLAC__stream_decoder_set_metadata_respond(decoder->private_->FLAC_stream_decoder, type); + return FLAC__stream_decoder_set_metadata_respond((FLAC__StreamDecoder*)decoder, type); } OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_application(OggFLAC__StreamDecoder *decoder, const FLAC__byte id[4]) @@ -277,7 +405,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_application( FLAC__ASSERT(0 != decoder->protected_); if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) return false; - return FLAC__stream_decoder_set_metadata_respond_application(decoder->private_->FLAC_stream_decoder, id); + return FLAC__stream_decoder_set_metadata_respond_application((FLAC__StreamDecoder*)decoder, id); } OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_all(OggFLAC__StreamDecoder *decoder) @@ -287,7 +415,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_all(OggFLAC_ FLAC__ASSERT(0 != decoder->protected_); if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) return false; - return FLAC__stream_decoder_set_metadata_respond_all(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_set_metadata_respond_all((FLAC__StreamDecoder*)decoder); } OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore(OggFLAC__StreamDecoder *decoder, FLAC__MetadataType type) @@ -297,7 +425,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore(OggFLAC__Stre FLAC__ASSERT(0 != decoder->protected_); if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) return false; - return FLAC__stream_decoder_set_metadata_ignore(decoder->private_->FLAC_stream_decoder, type); + return FLAC__stream_decoder_set_metadata_ignore((FLAC__StreamDecoder*)decoder, type); } OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_application(OggFLAC__StreamDecoder *decoder, const FLAC__byte id[4]) @@ -307,7 +435,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_application(O FLAC__ASSERT(0 != decoder->protected_); if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) return false; - return FLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->FLAC_stream_decoder, id); + return FLAC__stream_decoder_set_metadata_ignore_application((FLAC__StreamDecoder*)decoder, id); } OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_all(OggFLAC__StreamDecoder *decoder) @@ -317,7 +445,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_all(OggFLAC__ FLAC__ASSERT(0 != decoder->protected_); if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED) return false; - return FLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_set_metadata_ignore_all((FLAC__StreamDecoder*)decoder); } OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__stream_decoder_get_state(const OggFLAC__StreamDecoder *decoder) @@ -331,7 +459,7 @@ OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_decoder_get_FLAC_stream_dec { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); - return FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder); } OggFLAC_API const char *OggFLAC__stream_decoder_get_resolved_state_string(const OggFLAC__StreamDecoder *decoder) @@ -339,42 +467,56 @@ OggFLAC_API const char *OggFLAC__stream_decoder_get_resolved_state_string(const if(decoder->protected_->state != OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) return OggFLAC__StreamDecoderStateString[decoder->protected_->state]; else - return FLAC__stream_decoder_get_resolved_state_string(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_get_resolved_state_string((FLAC__StreamDecoder*)decoder); +} + +OggFLAC_API FLAC__bool OggFLAC__stream_decoder_get_md5_checking(const OggFLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + return FLAC__stream_decoder_get_md5_checking((FLAC__StreamDecoder*)decoder); +} + +OggFLAC_API FLAC__uint64 OggFLAC__stream_decoder_get_total_samples(const OggFLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + return FLAC__stream_decoder_get_total_samples((FLAC__StreamDecoder*)decoder); } OggFLAC_API unsigned OggFLAC__stream_decoder_get_channels(const OggFLAC__StreamDecoder *decoder) { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); - return FLAC__stream_decoder_get_channels(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_get_channels((FLAC__StreamDecoder*)decoder); } OggFLAC_API FLAC__ChannelAssignment OggFLAC__stream_decoder_get_channel_assignment(const OggFLAC__StreamDecoder *decoder) { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); - return FLAC__stream_decoder_get_channel_assignment(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_get_channel_assignment((FLAC__StreamDecoder*)decoder); } OggFLAC_API unsigned OggFLAC__stream_decoder_get_bits_per_sample(const OggFLAC__StreamDecoder *decoder) { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); - return FLAC__stream_decoder_get_bits_per_sample(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_get_bits_per_sample((FLAC__StreamDecoder*)decoder); } OggFLAC_API unsigned OggFLAC__stream_decoder_get_sample_rate(const OggFLAC__StreamDecoder *decoder) { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); - return FLAC__stream_decoder_get_sample_rate(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_get_sample_rate((FLAC__StreamDecoder*)decoder); } OggFLAC_API unsigned OggFLAC__stream_decoder_get_blocksize(const OggFLAC__StreamDecoder *decoder) { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); - return FLAC__stream_decoder_get_blocksize(decoder->private_->FLAC_stream_decoder); + return FLAC__stream_decoder_get_blocksize((FLAC__StreamDecoder*)decoder); } OggFLAC_API FLAC__bool OggFLAC__stream_decoder_flush(OggFLAC__StreamDecoder *decoder) @@ -385,7 +527,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_flush(OggFLAC__StreamDecoder *dec OggFLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect); - if(!FLAC__stream_decoder_flush(decoder->private_->FLAC_stream_decoder)) { + if(!FLAC__stream_decoder_flush((FLAC__StreamDecoder*)decoder)) { decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR; return false; } @@ -408,7 +550,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_reset(OggFLAC__StreamDecoder *dec OggFLAC__ogg_decoder_aspect_reset(&decoder->protected_->ogg_decoder_aspect); - if(!FLAC__stream_decoder_reset(decoder->private_->FLAC_stream_decoder)) { + if(!FLAC__stream_decoder_reset((FLAC__StreamDecoder*)decoder)) { decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR; return false; } @@ -423,7 +565,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_single(OggFLAC__StreamDec FLAC__bool ret; FLAC__ASSERT(0 != decoder); - if(FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) + if(FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM; if(decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM) @@ -431,7 +573,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_single(OggFLAC__StreamDec FLAC__ASSERT(decoder->protected_->state == OggFLAC__STREAM_DECODER_OK); - ret = FLAC__stream_decoder_process_single(decoder->private_->FLAC_stream_decoder); + ret = FLAC__stream_decoder_process_single((FLAC__StreamDecoder*)decoder); if(!ret) decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR; @@ -443,7 +585,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_metadata(Ogg FLAC__bool ret; FLAC__ASSERT(0 != decoder); - if(FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) + if(FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM; if(decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM) @@ -451,7 +593,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_metadata(Ogg FLAC__ASSERT(decoder->protected_->state == OggFLAC__STREAM_DECODER_OK); - ret = FLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->FLAC_stream_decoder); + ret = FLAC__stream_decoder_process_until_end_of_metadata((FLAC__StreamDecoder*)decoder); if(!ret) decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR; @@ -463,7 +605,27 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_stream(OggFL FLAC__bool ret; FLAC__ASSERT(0 != decoder); - if(FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) + if(FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) + decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM; + + if(decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM) + return true; + + FLAC__ASSERT(decoder->protected_->state == OggFLAC__STREAM_DECODER_OK); + + ret = FLAC__stream_decoder_process_until_end_of_stream((FLAC__StreamDecoder*)decoder); + if(!ret) + decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR; + + return ret; +} + +OggFLAC_API FLAC__bool OggFLAC__stream_decoder_skip_single_frame(OggFLAC__StreamDecoder *decoder) +{ + FLAC__bool ret; + FLAC__ASSERT(0 != decoder); + + if(FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM; if(decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM) @@ -471,13 +633,66 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_stream(OggFL FLAC__ASSERT(decoder->protected_->state == OggFLAC__STREAM_DECODER_OK); - ret = FLAC__stream_decoder_process_until_end_of_stream(decoder->private_->FLAC_stream_decoder); + ret = FLAC__stream_decoder_skip_single_frame((FLAC__StreamDecoder*)decoder); if(!ret) decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR; return ret; } +OggFLAC_API FLAC__bool OggFLAC__stream_decoder_seek_absolute(OggFLAC__StreamDecoder *decoder, FLAC__uint64 sample) +{ + FLAC__uint64 length; + + FLAC__ASSERT(0 != decoder); + + if(decoder->protected_->state != OggFLAC__STREAM_DECODER_OK && decoder->protected_->state != OggFLAC__STREAM_DECODER_END_OF_STREAM) + return false; + + if(0 == decoder->private_->seek_callback) + return false; + + FLAC__ASSERT(decoder->private_->seek_callback); + FLAC__ASSERT(decoder->private_->tell_callback); + FLAC__ASSERT(decoder->private_->length_callback); + FLAC__ASSERT(decoder->private_->eof_callback); + + if(OggFLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= OggFLAC__stream_decoder_get_total_samples(decoder)) + return false; + + decoder->private_->is_seeking = true; + + /* get the file length (currently our algorithm needs to know the length so it's also an error to get FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED) */ + if(decoder->private_->length_callback((FLAC__StreamDecoder*)decoder, &length, decoder->private_->client_data) != FLAC__STREAM_DECODER_LENGTH_STATUS_OK) { + decoder->private_->is_seeking = false; + return false; + } + + /* if we haven't finished processing the metadata yet, do that so we have the STREAMINFO */ + if( + FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA || + FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_READ_METADATA + ) { + if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder)) { + /* above call sets the state for us */ + decoder->private_->is_seeking = false; + return false; + } + /* check this again in case we didn't know total_samples the first time */ + if(OggFLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= OggFLAC__stream_decoder_get_total_samples(decoder)) { + decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR; + decoder->private_->is_seeking = false; + return false; + } + } + + { + FLAC__bool ok = seek_to_absolute_sample_(decoder, length, sample); + decoder->private_->is_seeking = false; + return ok; + } +} + /*********************************************************************** * @@ -488,6 +703,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_stream(OggFL void set_defaults_(OggFLAC__StreamDecoder *decoder) { decoder->private_->read_callback = 0; + decoder->private_->seek_callback = 0; + decoder->private_->tell_callback = 0; + decoder->private_->length_callback = 0; + decoder->private_->eof_callback = 0; decoder->private_->write_callback = 0; decoder->private_->metadata_callback = 0; decoder->private_->error_callback = 0; @@ -495,11 +714,67 @@ void set_defaults_(OggFLAC__StreamDecoder *decoder) OggFLAC__ogg_decoder_aspect_set_defaults(&decoder->protected_->ogg_decoder_aspect); } -FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *unused, FLAC__byte buffer[], unsigned *bytes, void *client_data) +/* + * This will forcibly set stdin to binary mode (for OSes that require it) + */ +FILE *get_binary_stdin_() { - OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data; + /* if something breaks here it is probably due to the presence or + * absence of an underscore before the identifiers 'setmode', + * 'fileno', and/or 'O_BINARY'; check your system header files. + */ +#if defined _MSC_VER || defined __MINGW32__ + _setmode(_fileno(stdin), _O_BINARY); +#elif defined __CYGWIN__ || defined __EMX__ + /* almost certainly not needed for any modern Cygwin, but let's be safe... */ + setmode(_fileno(stdin), _O_BINARY); +#endif - (void)unused; + return stdin; +} + +FLAC__StreamDecoderReadStatus read_callback2_(const FLAC__StreamDecoder *super, FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + const OggFLAC__StreamDecoder *decoder = (const OggFLAC__StreamDecoder *)super; + (void)client_data; + if(decoder->private_->eof_callback && decoder->private_->eof_callback((FLAC__StreamDecoder*)decoder, decoder->private_->client_data)) { + *bytes = 0; +#if 0 + /*@@@@@@ we used to do this: */ + stream_decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM; + /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */ +#endif + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } + else if(*bytes > 0) { + const FLAC__StreamDecoderReadStatus status = decoder->private_->read_callback(super, buffer, bytes, decoder->private_->client_data); + if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) { + decoder->protected_->state = OggFLAC__STREAM_DECODER_READ_ERROR; + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + } + else if(*bytes == 0) { + if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM || (decoder->private_->eof_callback && decoder->private_->eof_callback((FLAC__StreamDecoder*)decoder, decoder->private_->client_data))) { +#if 0 + /*@@@@@@ we used to do this: */ + stream_decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM; + /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */ +#endif + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } + else + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } + else + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } + else + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */ +} + +FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *super, FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + const OggFLAC__StreamDecoder *decoder = (const OggFLAC__StreamDecoder *)super; + (void)client_data; switch(OggFLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder, decoder->private_->client_data)) { case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK: @@ -528,32 +803,11 @@ FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *unused, } } -FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *unused, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) -{ - OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data; - (void)unused; - return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data); -} - -void metadata_callback_(const FLAC__StreamDecoder *unused, const FLAC__StreamMetadata *metadata, void *client_data) -{ - OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data; - (void)unused; - decoder->private_->metadata_callback(decoder, metadata, decoder->private_->client_data); -} - -void error_callback_(const FLAC__StreamDecoder *unused, FLAC__StreamDecoderErrorStatus status, void *client_data) -{ - OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data; - (void)unused; - decoder->private_->error_callback(decoder, status, decoder->private_->client_data); -} - OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) { OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)void_decoder; - switch(decoder->private_->read_callback(decoder, buffer, bytes, client_data)) { + switch(read_callback2_((FLAC__StreamDecoder*)decoder, buffer, bytes, client_data)) { case FLAC__STREAM_DECODER_READ_STATUS_CONTINUE: return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK; case FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM: @@ -566,3 +820,276 @@ OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decode return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT; } } + +FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *super, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super; + (void)client_data; + + if(decoder->private_->is_seeking) { + FLAC__uint64 this_frame_sample = frame->header.number.sample_number; + FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize; + FLAC__uint64 target_sample = decoder->private_->target_sample; + + FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + + decoder->private_->got_a_frame = true; + decoder->private_->last_frame = *frame; /* save the frame */ + if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */ + unsigned delta = (unsigned)(target_sample - this_frame_sample); + /* kick out of seek mode */ + decoder->private_->is_seeking = false; + /* shift out the samples before target_sample */ + if(delta > 0) { + unsigned channel; + const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS]; + for(channel = 0; channel < frame->header.channels; channel++) + newbuffer[channel] = buffer[channel] + delta; + decoder->private_->last_frame.header.blocksize -= delta; + decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta; + /* write the relevant samples */ + return decoder->private_->write_callback((FLAC__StreamDecoder*)decoder, &decoder->private_->last_frame, newbuffer, decoder->private_->client_data); + } + else { + /* write the relevant samples */ + return decoder->private_->write_callback((FLAC__StreamDecoder*)decoder, frame, buffer, decoder->private_->client_data); + } + } + else { + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + } + } + else + return decoder->private_->write_callback((FLAC__StreamDecoder*)decoder, frame, buffer, decoder->private_->client_data); +} + +void metadata_callback_(const FLAC__StreamDecoder *super, const FLAC__StreamMetadata *metadata, void *client_data) +{ + OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super; + (void)client_data; + + if(!decoder->private_->is_seeking) + decoder->private_->metadata_callback((FLAC__StreamDecoder*)decoder, metadata, decoder->private_->client_data); +} + +void error_callback_(const FLAC__StreamDecoder *super, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super; + (void)client_data; + + if(!decoder->private_->is_seeking) + decoder->private_->error_callback((FLAC__StreamDecoder*)decoder, status, decoder->private_->client_data); +} + +FLAC__bool seek_to_absolute_sample_(OggFLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample) +{ + FLAC__uint64 left_pos = 0, right_pos = stream_length; + FLAC__uint64 left_sample = 0, right_sample = OggFLAC__stream_decoder_get_total_samples(decoder); + FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */ + FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */ + FLAC__bool did_a_seek; + unsigned iteration = 0; + + /* In the first iterations, we will calculate the target byte position + * by the distance from the target sample to left_sample and + * right_sample (let's call it "proportional search"). After that, we + * will switch to binary search. + */ + unsigned BINARY_SEARCH_AFTER_ITERATION = 2; + + /* We will switch to a linear search once our current sample is less + * than this number of samples ahead of the target sample + */ + static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2; + + /* If the total number of samples is unknown, use a large value, and + * force binary search immediately. + */ + if(right_sample == 0) { + right_sample = (FLAC__uint64)(-1); + BINARY_SEARCH_AFTER_ITERATION = 0; + } + + decoder->private_->target_sample = target_sample; + for( ; ; iteration++) { + if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) { + if (iteration >= BINARY_SEARCH_AFTER_ITERATION) { + pos = (right_pos + left_pos) / 2; + } + else { +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#if defined _MSC_VER || defined __MINGW32__ + /* with MSVC you have to spoon feed it the casting */ + pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos)); +#else + pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos)); +#endif +#else + /* a little less accurate: */ + if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff)) + pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample)); + else /* @@@ WATCHOUT, ~2TB limit */ + pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16)); +#endif + /* @@@ TODO: might want to limit pos to some distance + * before EOF, to make sure we land before the last frame, + * thereby getting a this_fram_sample and so having a better + * estimate. @@@@@@DELETE:this would also mostly (or totally if we could + * be sure to land before the last frame) avoid the + * end-of-stream case we have to check later. + */ + } + + /* physical seek */ + if(decoder->private_->seek_callback((FLAC__StreamDecoder*)decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) { + decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + if(!OggFLAC__stream_decoder_flush(decoder)) { + /* above call sets the state for us */ + return false; + } + did_a_seek = true; + } + else + did_a_seek = false; + + decoder->private_->got_a_frame = false; + if(!OggFLAC__stream_decoder_process_single(decoder)) { + decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + if(!decoder->private_->got_a_frame) { + if(did_a_seek) { + /* this can happen if we seek to a point after the last frame; we drop + * to binary search right away in this case to avoid any wasted + * iterations of proportional search. + */ + right_pos = pos; + BINARY_SEARCH_AFTER_ITERATION = 0; + } + else { + /* this can probably only happen if total_samples is unknown and the + * target_sample is past the end of the stream + */ + decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + } + /* our write callback will change the state when it gets to the target frame */ + else if(!decoder->private_->is_seeking/*@@@@@@ && decoder->protected_->state != OggFLAC__STREAM_DECODER_END_OF_STREAM*/) { + break; + } + else { + this_frame_sample = decoder->private_->last_frame.header.number.sample_number; + FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + + if (did_a_seek) { + if (this_frame_sample <= target_sample) { + /* The 'equal' case should not happen, since + * OggFLAC__stream_decoder_process_single() + * should recognize that it has hit the + * target sample and we would exit through + * the 'break' above. + */ + FLAC__ASSERT(this_frame_sample != target_sample); + + left_sample = this_frame_sample; + /* sanity check to avoid infinite loop */ + if (left_pos == pos) { + decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + left_pos = pos; + } + else if(this_frame_sample > target_sample) { + right_sample = this_frame_sample; + /* sanity check to avoid infinite loop */ + if (right_pos == pos) { + decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + right_pos = pos; + } + } + } + } + + return true; +} + +FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *super, FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super; + (void)client_data; + + if(*bytes > 0) { + *bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, decoder->private_->file); + if(ferror(decoder->private_->file)) + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + else if(*bytes == 0) + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + else + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } + else + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */ +} + +FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *super, FLAC__uint64 absolute_byte_offset, void *client_data) +{ + OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super; + (void)client_data; + + if(decoder->private_->file == stdin) + return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; + else if(fseeko(decoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) + return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; + else + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; +} + +FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *super, FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super; + off_t pos; + (void)client_data; + + if(decoder->private_->file == stdin) /*@@@@@@ may work for stdin */ + return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED; + else if((pos = ftello(decoder->private_->file)) < 0) + return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; + else { + *absolute_byte_offset = (FLAC__uint64)pos; + return FLAC__STREAM_DECODER_TELL_STATUS_OK; + } +} + +FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *super, FLAC__uint64 *stream_length, void *client_data) +{ + OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super; + struct stat filestats; + (void)client_data; + + if(decoder->private_->file == stdin) + return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; +#ifdef OLD_STAT_WAY //@@@@@@ + else if(0 == decoder->private_->filename || fstat(fileno(decoder->private_->file), &filestats) != 0) +#endif + else if(fstat(fileno(decoder->private_->file), &filestats) != 0) + return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; + else { + *stream_length = (FLAC__uint64)filestats.st_size; + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; + } +} + +FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *super, void *client_data) +{ + OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super; + (void)client_data; + + if(decoder->private_->file == stdin) /*@@@@@@ feof() may work for stdin */ + return false; + return feof(decoder->private_->file)? true : false; +} diff --git a/src/libOggFLAC/stream_encoder.c b/src/libOggFLAC/stream_encoder.c index 1c7c95a8..53e35b62 100644 --- a/src/libOggFLAC/stream_encoder.c +++ b/src/libOggFLAC/stream_encoder.c @@ -33,11 +33,32 @@ # include <config.h> #endif +#if defined _MSC_VER || defined __MINGW32__ +#include <io.h> /* for _setmode() */ +#include <fcntl.h> /* for _O_BINARY */ +#endif +#if defined __CYGWIN__ || defined __EMX__ +#include <io.h> /* for setmode(), O_BINARY */ +#include <fcntl.h> /* for _O_BINARY */ +#endif #include <stdio.h> #include <stdlib.h> /* for calloc() */ +#include <string.h> /* for memcpy() */ +#include <sys/types.h> /* for off_t */ +#if defined _MSC_VER || defined __MINGW32__ +/*@@@ [2G limit] hacks for MSVC6 */ +#define fseeko fseek +#define ftello ftell +#endif #include "FLAC/assert.h" #include "OggFLAC/stream_encoder.h" #include "protected/stream_encoder.h" +#include "private/ogg_helper.h" + +#ifdef max +#undef max +#endif +#define max(a,b) ((a)>(b)?(a):(b)) /*********************************************************************** * @@ -53,6 +74,11 @@ extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEn static void set_defaults_(OggFLAC__StreamEncoder *encoder); static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); +static OggFLAC__StreamEncoderReadStatus file_read_callback_(const OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data); +static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data); +static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); +static FILE *get_binary_stdout_(); /*********************************************************************** @@ -62,10 +88,24 @@ static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__S ***********************************************************************/ typedef struct OggFLAC__StreamEncoderPrivate { - OggFLAC__StreamEncoderWriteCallback write_callback; - OggFLAC__StreamEncoderMetadataCallback metadata_callback; + OggFLAC__StreamEncoderReadCallback read_callback; + FLAC__StreamEncoderWriteCallback write_callback; + FLAC__StreamEncoderSeekCallback seek_callback; + FLAC__StreamEncoderTellCallback tell_callback; + FLAC__StreamEncoderMetadataCallback metadata_callback; + FLAC__StreamEncoderProgressCallback progress_callback; void *client_data; +#if 0 //@@@@@@ FLAC__StreamEncoder *FLAC_stream_encoder; +#endif + FLAC__StreamMetadata_SeekTable *seek_table; + /* internal vars (all the above are class settings) */ + unsigned first_seekpoint_to_check; + FILE *file; /* only used when encoding to a file */ + FLAC__uint64 bytes_written; + FLAC__uint64 samples_written; + unsigned frames_written; + unsigned total_frames_estimate; } OggFLAC__StreamEncoderPrivate; @@ -77,12 +117,19 @@ typedef struct OggFLAC__StreamEncoderPrivate { OggFLAC_API const char * const OggFLAC__StreamEncoderStateString[] = { "OggFLAC__STREAM_ENCODER_OK", + "OggFLAC__STREAM_ENCODER_UNINITIALIZED", "OggFLAC__STREAM_ENCODER_OGG_ERROR", "OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR", - "OggFLAC__STREAM_ENCODER_INVALID_CALLBACK", - "OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR", - "OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED", - "OggFLAC__STREAM_ENCODER_UNINITIALIZED" + "OggFLAC__STREAM_ENCODER_CLIENT_ERROR", + "OggFLAC__STREAM_ENCODER_IO_ERROR", + "OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR" +}; + +OggFLAC_API const char * const OggFLAC__treamEncoderReadStatusString[] = { + "OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE", + "OggFLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM", + "OggFLAC__STREAM_ENCODER_READ_STATUS_ABORT", + "OggFLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED" }; @@ -94,6 +141,9 @@ OggFLAC_API const char * const OggFLAC__StreamEncoderStateString[] = { OggFLAC_API OggFLAC__StreamEncoder *OggFLAC__stream_encoder_new() { OggFLAC__StreamEncoder *encoder; + FLAC__StreamEncoder *parent; + + FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ encoder = (OggFLAC__StreamEncoder*)calloc(1, sizeof(OggFLAC__StreamEncoder)); if(encoder == 0) { @@ -113,13 +163,16 @@ OggFLAC_API OggFLAC__StreamEncoder *OggFLAC__stream_encoder_new() return 0; } - encoder->private_->FLAC_stream_encoder = FLAC__stream_encoder_new(); - if(0 == encoder->private_->FLAC_stream_encoder) { + parent = FLAC__stream_encoder_new(); + if(0 == parent) { free(encoder->private_); free(encoder->protected_); free(encoder); return 0; } + encoder->super_ = *parent; + + encoder->private_->file = 0; set_defaults_(encoder); @@ -133,15 +186,15 @@ OggFLAC_API void OggFLAC__stream_encoder_delete(OggFLAC__StreamEncoder *encoder) FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->protected_); FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); (void)OggFLAC__stream_encoder_finish(encoder); - FLAC__stream_encoder_delete(encoder->private_->FLAC_stream_encoder); - free(encoder->private_); free(encoder->protected_); - free(encoder); + /* don't free(encoder) because FLAC__stream_encoder_delete() will do it */ + + /* call superclass destructor last */ + FLAC__stream_encoder_delete((FLAC__StreamEncoder*)encoder); } @@ -151,27 +204,126 @@ OggFLAC_API void OggFLAC__stream_encoder_delete(OggFLAC__StreamEncoder *encoder) * ***********************************************************************/ -OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_init(OggFLAC__StreamEncoder *encoder) +OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_stream(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderReadCallback read_callback, FLAC__StreamEncoderWriteCallback write_callback, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderTellCallback tell_callback, FLAC__StreamEncoderMetadataCallback metadata_callback, void *client_data) { FLAC__ASSERT(0 != encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) - return encoder->protected_->state = OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED; + return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED; + + if(0 == write_callback || (seek_callback && (0 == read_callback || 0 == tell_callback))) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS; - if(0 == encoder->private_->write_callback || 0 == encoder->private_->metadata_callback) - return encoder->protected_->state = OggFLAC__STREAM_ENCODER_INVALID_CALLBACK; + /* check seek table before FLAC__stream_encoder_init_stream() does, just to avoid messing up the encoder state for a trivial error */ + if(0 != encoder->private_->seek_table && !FLAC__format_seektable_is_legal(encoder->private_->seek_table)) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; - if(!OggFLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect)) - return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; + /* set state to OK; from here on, errors are fatal and we'll override the state then */ + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OK; + + if(!OggFLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect)) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } - FLAC__stream_encoder_set_write_callback(encoder->private_->FLAC_stream_encoder, write_callback_); - FLAC__stream_encoder_set_metadata_callback(encoder->private_->FLAC_stream_encoder, metadata_callback_); - FLAC__stream_encoder_set_client_data(encoder->private_->FLAC_stream_encoder, encoder); + encoder->private_->read_callback = read_callback; + encoder->private_->write_callback = write_callback; + encoder->private_->seek_callback = seek_callback; + encoder->private_->tell_callback = tell_callback; + encoder->private_->metadata_callback = metadata_callback; + encoder->private_->client_data = client_data; + + /* + * These must be done before we init the stream encoder because that + * calls the write_callback, which uses these values. + */ + encoder->private_->first_seekpoint_to_check = 0; + encoder->private_->samples_written = 0; + encoder->protected_->streaminfo_offset = 0; + encoder->protected_->seektable_offset = 0; + encoder->protected_->audio_offset = 0; + + /* we do our own special metadata updating inside Ogg here, so we don't pass in our seek/tell callbacks */ + if(FLAC__stream_encoder_init_stream((FLAC__StreamEncoder*)encoder, write_callback_, /*seek_callback=*/0, /*tell_callback=*/0, metadata_callback_, /*client_data=*/encoder) != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } - if(FLAC__stream_encoder_init(encoder->private_->FLAC_stream_encoder) != FLAC__STREAM_ENCODER_OK) - return encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR; + /* + * Initializing the stream encoder writes all the metadata, so we + * save the stream offset now. + */ + if(encoder->private_->tell_callback && encoder->private_->tell_callback((FLAC__StreamEncoder*)encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */ + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } - return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OK; + return FLAC__STREAM_ENCODER_INIT_STATUS_OK; +} + +OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_FILE(OggFLAC__StreamEncoder *encoder, FILE *file, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data) +{ + FLAC__StreamEncoderInitStatus init_status; + + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != file); + + if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) + return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED; + + /* + * To make sure that our file does not go unclosed after an error, we + * must assign the FILE pointer before any further error can occur in + * this routine. + */ + if(file == stdout) + file = get_binary_stdout_(); /* just to be safe */ + + encoder->private_->file = file; + + encoder->private_->progress_callback = progress_callback; + encoder->private_->bytes_written = 0; + encoder->private_->samples_written = 0; + encoder->private_->frames_written = 0; + + init_status = OggFLAC__stream_encoder_init_stream(encoder, file_read_callback_, file_write_callback_, file_seek_callback_, file_tell_callback_, /*metadata_callback=*/0, client_data); + if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + /* the above function sets the state for us in case of an error */ + return init_status; + } + + { + unsigned blocksize = OggFLAC__stream_encoder_get_blocksize(encoder); + + FLAC__ASSERT(blocksize != 0); + encoder->private_->total_frames_estimate = (unsigned)((OggFLAC__stream_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize); + } + + return init_status; +} + +OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_file(OggFLAC__StreamEncoder *encoder, const char *filename, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data) +{ + FILE *file; + + FLAC__ASSERT(0 != encoder); + + /* + * To make sure that our file does not go unclosed after an error, we + * have to do the same entrance checks here that are later performed + * in FLAC__stream_encoder_init_FILE() before the FILE* is assigned. + */ + if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) + return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED; + + file = filename? fopen(filename, "w+b") : stdout; + + if(file == 0) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_IO_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + return OggFLAC__stream_encoder_init_FILE(encoder, file, progress_callback, client_data); } OggFLAC_API void OggFLAC__stream_encoder_finish(OggFLAC__StreamEncoder *encoder) @@ -183,9 +335,9 @@ OggFLAC_API void OggFLAC__stream_encoder_finish(OggFLAC__StreamEncoder *encoder) if(encoder->protected_->state == OggFLAC__STREAM_ENCODER_UNINITIALIZED) return; - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); - FLAC__stream_encoder_finish(encoder->private_->FLAC_stream_encoder); + FLAC__stream_encoder_finish((FLAC__StreamEncoder*)encoder); OggFLAC__ogg_encoder_aspect_finish(&encoder->protected_->ogg_encoder_aspect); @@ -199,7 +351,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_serial_number(OggFLAC__Stream FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; OggFLAC__ogg_encoder_aspect_set_serial_number(&encoder->protected_->ogg_encoder_aspect, value); @@ -211,10 +363,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_verify(OggFLAC__StreamEncoder FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_verify(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_verify((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_streamable_subset(OggFLAC__StreamEncoder *encoder, FLAC__bool value) @@ -222,10 +374,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_streamable_subset(OggFLAC__St FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_streamable_subset(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_streamable_subset((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_mid_side_stereo(OggFLAC__StreamEncoder *encoder, FLAC__bool value) @@ -233,10 +385,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_mid_side_stereo(OggFLAC__S FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_do_mid_side_stereo((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_loose_mid_side_stereo(OggFLAC__StreamEncoder *encoder, FLAC__bool value) @@ -244,10 +396,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_loose_mid_side_stereo(OggFLAC FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_loose_mid_side_stereo((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_channels(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -255,10 +407,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_channels(OggFLAC__StreamEncod FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_channels(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_channels((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_bits_per_sample(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -266,10 +418,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_bits_per_sample(OggFLAC__Stre FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_bits_per_sample((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_sample_rate(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -277,10 +429,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_sample_rate(OggFLAC__StreamEn FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_sample_rate(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_sample_rate((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_blocksize(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -288,10 +440,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_blocksize(OggFLAC__StreamEnco FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_blocksize((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_apodization(OggFLAC__StreamEncoder *encoder, const char *specification) @@ -299,10 +451,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_apodization(OggFLAC__StreamEn FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_apodization(encoder->private_->FLAC_stream_encoder, specification); + return FLAC__stream_encoder_set_apodization((FLAC__StreamEncoder*)encoder, specification); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_lpc_order(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -310,10 +462,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_lpc_order(OggFLAC__Stream FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_max_lpc_order((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_qlp_coeff_precision(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -321,10 +473,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_qlp_coeff_precision(OggFLAC__ FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_qlp_coeff_precision((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(OggFLAC__StreamEncoder *encoder, FLAC__bool value) @@ -332,10 +484,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(OggF FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_do_qlp_coeff_prec_search((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_escape_coding(OggFLAC__StreamEncoder *encoder, FLAC__bool value) @@ -343,10 +495,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_escape_coding(OggFLAC__Str FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_do_escape_coding((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_exhaustive_model_search(OggFLAC__StreamEncoder *encoder, FLAC__bool value) @@ -354,10 +506,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_exhaustive_model_search(Og FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_do_exhaustive_model_search((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_min_residual_partition_order(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -365,10 +517,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_min_residual_partition_order( FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_min_residual_partition_order((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_residual_partition_order(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -376,10 +528,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_residual_partition_order( FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_max_residual_partition_order((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_rice_parameter_search_dist(OggFLAC__StreamEncoder *encoder, unsigned value) @@ -387,10 +539,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_rice_parameter_search_dist(Og FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_rice_parameter_search_dist((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLAC__StreamEncoder *encoder, FLAC__uint64 value) @@ -398,10 +550,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLA FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_set_total_samples_estimate((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks) @@ -409,7 +561,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncod FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); + //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; /* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */ @@ -425,49 +577,24 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncod } } } + if(0 != metadata && num_blocks > 0) { + unsigned i; + for(i = 0; i < num_blocks; i++) { + /* keep track of any SEEKTABLE block */ + if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) { + encoder->private_->seek_table = &metadata[i]->data.seek_table; + break; /* take only the first one */ + } + } + } if(!OggFLAC__ogg_encoder_aspect_set_num_metadata(&encoder->protected_->ogg_encoder_aspect, num_blocks)) return false; - return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks); -} - -OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_write_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderWriteCallback value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != value); - if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) - return false; - encoder->private_->write_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderMetadataCallback value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - FLAC__ASSERT(0 != value); - if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) - return false; - encoder->private_->metadata_callback = value; - return true; -} - -OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_client_data(OggFLAC__StreamEncoder *encoder, void *value) -{ - FLAC__ASSERT(0 != encoder); - FLAC__ASSERT(0 != encoder->private_); - FLAC__ASSERT(0 != encoder->protected_); - if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) - return false; - encoder->private_->client_data = value; - return true; + return FLAC__stream_encoder_set_metadata((FLAC__StreamEncoder*)encoder, metadata, num_blocks); } /* * These three functions are not static, but not publically exposed in - * include/FLAC/ either. They are used by the test suite. + * include/OggFLAC/ either. They are used by the test suite. */ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_constant_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value) { @@ -476,7 +603,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_constant_subframes(OggFLA FLAC__ASSERT(0 != encoder->protected_); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_disable_constant_subframes(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_disable_constant_subframes((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_fixed_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value) @@ -486,7 +613,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_fixed_subframes(OggFLAC__ FLAC__ASSERT(0 != encoder->protected_); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_disable_fixed_subframes(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_disable_fixed_subframes((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_verbatim_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value) @@ -496,7 +623,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_verbatim_subframes(OggFLA FLAC__ASSERT(0 != encoder->protected_); if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED) return false; - return FLAC__stream_encoder_disable_verbatim_subframes(encoder->private_->FLAC_stream_encoder, value); + return FLAC__stream_encoder_disable_verbatim_subframes((FLAC__StreamEncoder*)encoder, value); } OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_get_state(const OggFLAC__StreamEncoder *encoder) @@ -512,7 +639,7 @@ OggFLAC_API FLAC__StreamEncoderState OggFLAC__stream_encoder_get_FLAC_stream_enc FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_state(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_state((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_encoder_get_verify_decoder_state(const OggFLAC__StreamEncoder *encoder) @@ -520,7 +647,7 @@ OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_encoder_get_verify_decoder_ FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_verify_decoder_state((FLAC__StreamEncoder*)encoder); } OggFLAC_API const char *OggFLAC__stream_encoder_get_resolved_state_string(const OggFLAC__StreamEncoder *encoder) @@ -528,14 +655,14 @@ OggFLAC_API const char *OggFLAC__stream_encoder_get_resolved_state_string(const if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) return OggFLAC__StreamEncoderStateString[encoder->protected_->state]; else - return FLAC__stream_encoder_get_resolved_state_string(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_resolved_state_string((FLAC__StreamEncoder*)encoder); } OggFLAC_API void OggFLAC__stream_encoder_get_verify_decoder_error_stats(const OggFLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got) { FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); - FLAC__stream_encoder_get_verify_decoder_error_stats(encoder->private_->FLAC_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got); + FLAC__stream_encoder_get_verify_decoder_error_stats((FLAC__StreamEncoder*)encoder, absolute_sample, frame_number, channel, sample, expected, got); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_verify(const OggFLAC__StreamEncoder *encoder) @@ -543,7 +670,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_verify(const OggFLAC__StreamE FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_verify(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_verify((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_streamable_subset(const OggFLAC__StreamEncoder *encoder) @@ -551,7 +678,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_streamable_subset(const OggFL FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_streamable_subset(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_streamable_subset((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_mid_side_stereo(const OggFLAC__StreamEncoder *encoder) @@ -559,7 +686,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_mid_side_stereo(const OggF FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_do_mid_side_stereo((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_loose_mid_side_stereo(const OggFLAC__StreamEncoder *encoder) @@ -567,7 +694,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_loose_mid_side_stereo(const O FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_loose_mid_side_stereo((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_channels(const OggFLAC__StreamEncoder *encoder) @@ -575,7 +702,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_channels(const OggFLAC__StreamE FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_channels(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_channels((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_bits_per_sample(const OggFLAC__StreamEncoder *encoder) @@ -583,7 +710,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_bits_per_sample(const OggFLAC__ FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_bits_per_sample((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_sample_rate(const OggFLAC__StreamEncoder *encoder) @@ -591,7 +718,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_sample_rate(const OggFLAC__Stre FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_sample_rate(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_sample_rate((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_blocksize(const OggFLAC__StreamEncoder *encoder) @@ -599,7 +726,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_blocksize(const OggFLAC__Stream FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_blocksize((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_lpc_order(const OggFLAC__StreamEncoder *encoder) @@ -607,7 +734,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_lpc_order(const OggFLAC__St FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_max_lpc_order((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_qlp_coeff_precision(const OggFLAC__StreamEncoder *encoder) @@ -615,7 +742,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_qlp_coeff_precision(const OggFL FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_qlp_coeff_precision((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__StreamEncoder *encoder) @@ -623,7 +750,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_qlp_coeff_prec_search(cons FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_do_qlp_coeff_prec_search((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_escape_coding(const OggFLAC__StreamEncoder *encoder) @@ -631,7 +758,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_escape_coding(const OggFLA FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_do_escape_coding((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_exhaustive_model_search(const OggFLAC__StreamEncoder *encoder) @@ -639,7 +766,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_exhaustive_model_search(co FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_do_exhaustive_model_search((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_min_residual_partition_order(const OggFLAC__StreamEncoder *encoder) @@ -647,7 +774,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_min_residual_partition_order(co FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_min_residual_partition_order((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_residual_partition_order(const OggFLAC__StreamEncoder *encoder) @@ -655,7 +782,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_residual_partition_order(co FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_max_residual_partition_order((FLAC__StreamEncoder*)encoder); } OggFLAC_API unsigned OggFLAC__stream_encoder_get_rice_parameter_search_dist(const OggFLAC__StreamEncoder *encoder) @@ -663,7 +790,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_rice_parameter_search_dist(cons FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_rice_parameter_search_dist((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__uint64 OggFLAC__stream_encoder_get_total_samples_estimate(const OggFLAC__StreamEncoder *encoder) @@ -671,7 +798,7 @@ OggFLAC_API FLAC__uint64 OggFLAC__stream_encoder_get_total_samples_estimate(cons FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder); + return FLAC__stream_encoder_get_total_samples_estimate((FLAC__StreamEncoder*)encoder); } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process(OggFLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples) @@ -679,7 +806,12 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process(OggFLAC__StreamEncoder *e FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_process(encoder->private_->FLAC_stream_encoder, buffer, samples); + if(!FLAC__stream_encoder_process((FLAC__StreamEncoder*)encoder, buffer, samples)) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR; + return false; + } + else + return true; } OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process_interleaved(OggFLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples) @@ -687,7 +819,12 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process_interleaved(OggFLAC__Stre FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); FLAC__ASSERT(0 != encoder->protected_); - return FLAC__stream_encoder_process_interleaved(encoder->private_->FLAC_stream_encoder, buffer, samples); + if(!FLAC__stream_encoder_process_interleaved((FLAC__StreamEncoder*)encoder, buffer, samples)) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR; + return false; + } + else + return true; } /*********************************************************************** @@ -699,30 +836,376 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process_interleaved(OggFLAC__Stre void set_defaults_(OggFLAC__StreamEncoder *encoder) { FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + encoder->private_->read_callback = 0; encoder->private_->write_callback = 0; + encoder->private_->seek_callback = 0; + encoder->private_->tell_callback = 0; encoder->private_->metadata_callback = 0; + encoder->private_->progress_callback = 0; encoder->private_->client_data = 0; + + encoder->private_->seek_table = 0; + OggFLAC__ogg_encoder_aspect_set_defaults(&encoder->protected_->ogg_encoder_aspect); } -FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) +FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *super, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) { - OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)client_data; - const FLAC__uint64 total_samples_estimate = FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder); + OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super; + FLAC__StreamEncoderWriteStatus status; + FLAC__uint64 output_position; + + (void)client_data; /* silence compiler warning about unused parameter */ + + /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */ + if(encoder->private_->tell_callback && encoder->private_->tell_callback((FLAC__StreamEncoder*)encoder, &output_position, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + } + + /* + * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets. + */ + if(samples == 0) { + FLAC__MetadataType type = (buffer[0] & 0x7f); + if(type == FLAC__METADATA_TYPE_STREAMINFO) + encoder->protected_->streaminfo_offset = output_position; + else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0) + encoder->protected_->seektable_offset = output_position; + } + + /* + * Mark the current seek point if hit (if audio_offset == 0 that + * means we're still writing metadata and haven't hit the first + * frame yet) + */ + if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) { + const unsigned blocksize = FLAC__stream_encoder_get_blocksize((FLAC__StreamEncoder*)encoder); + const FLAC__uint64 frame_first_sample = encoder->private_->samples_written; + const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1; + FLAC__uint64 test_sample; + unsigned i; + for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) { + test_sample = encoder->private_->seek_table->points[i].sample_number; + if(test_sample > frame_last_sample) { + break; + } + else if(test_sample >= frame_first_sample) { + encoder->private_->seek_table->points[i].sample_number = frame_first_sample; + encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset; + encoder->private_->seek_table->points[i].frame_samples = blocksize; + encoder->private_->first_seekpoint_to_check++; + /* DO NOT: "break;" and here's why: + * The seektable template may contain more than one target + * sample for any given frame; we will keep looping, generating + * duplicate seekpoints for them, and we'll clean it up later, + * just before writing the seektable back to the metadata. + */ + } + else { + encoder->private_->first_seekpoint_to_check++; + } + } + } - (void)unused; - FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused); + status = OggFLAC__ogg_encoder_aspect_write_callback_wrapper(&encoder->protected_->ogg_encoder_aspect, FLAC__stream_encoder_get_total_samples_estimate((FLAC__StreamEncoder*)encoder), buffer, bytes, samples, current_frame, (OggFLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback, encoder, encoder->private_->client_data); - return OggFLAC__ogg_encoder_aspect_write_callback_wrapper(&encoder->protected_->ogg_encoder_aspect, total_samples_estimate, buffer, bytes, samples, current_frame, (OggFLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback, encoder, encoder->private_->client_data); + if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) + encoder->private_->samples_written += samples; + else + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; + + return status; } -void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMetadata *metadata, void *client_data) +void metadata_callback_(const FLAC__StreamEncoder *super, const FLAC__StreamMetadata *metadata, void *client_data) { - OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)client_data; + OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super; + FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)]; + const FLAC__uint64 samples = metadata->data.stream_info.total_samples; + const unsigned min_framesize = metadata->data.stream_info.min_framesize; + const unsigned max_framesize = metadata->data.stream_info.max_framesize; + ogg_page page; + + FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO); + + /* We get called by the stream encoder when the encoding process + * has finished so that we can update the STREAMINFO and SEEKTABLE + * blocks. + */ + + (void)client_data; /* silence compiler warning about unused parameter */ + + /* All this is based on intimate knowledge of the stream header + * layout, but a change to the header format that would break this + * would also break all streams encoded in the previous format. + */ + + /** + ** Write STREAMINFO stats + **/ + simple_ogg_page__init(&page); + if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) { + simple_ogg_page__clear(&page); + return; /* state already set */ + } - (void)unused; - FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused); + /* + * Write MD5 signature + */ + { + const unsigned md5_offset = + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN + + FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN + ) / 8; + + if(md5_offset + 16 > (unsigned)page.body_len) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; + simple_ogg_page__clear(&page); + return; + } + memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16); + } + + /* + * Write total samples + */ + { + const unsigned total_samples_byte_offset = + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN + + FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN + - 4 + ) / 8; + + if(total_samples_byte_offset + 5 > (unsigned)page.body_len) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; + simple_ogg_page__clear(&page); + return; + } + b[0] = (FLAC__byte)page.body[total_samples_byte_offset] & 0xF0; + b[0] |= (FLAC__byte)((samples >> 32) & 0x0F); + b[1] = (FLAC__byte)((samples >> 24) & 0xFF); + b[2] = (FLAC__byte)((samples >> 16) & 0xFF); + b[3] = (FLAC__byte)((samples >> 8) & 0xFF); + b[4] = (FLAC__byte)(samples & 0xFF); + memcpy(page.body + total_samples_byte_offset, b, 5); + } + + /* + * Write min/max framesize + */ + { + const unsigned min_framesize_offset = + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + ) / 8; + + if(min_framesize_offset + 6 > (unsigned)page.body_len) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; + simple_ogg_page__clear(&page); + return; + } + b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF); + b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF); + b[2] = (FLAC__byte)(min_framesize & 0xFF); + b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF); + b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF); + b[5] = (FLAC__byte)(max_framesize & 0xFF); + memcpy(page.body + min_framesize_offset, b, 6); + } + if(!simple_ogg_page__set_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) { + simple_ogg_page__clear(&page); + return; /* state already set */ + } + simple_ogg_page__clear(&page); + + /* + * Write seektable + */ + if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) { + unsigned i; + FLAC__byte *p; + + FLAC__format_seektable_sort(encoder->private_->seek_table); + + FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table)); + + simple_ogg_page__init(&page); + if(!simple_ogg_page__get_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) { + simple_ogg_page__clear(&page); + return; /* state already set */ + } + + if(FLAC__STREAM_METADATA_HEADER_LENGTH + (18*encoder->private_->seek_table->num_points) > (unsigned)page.body_len) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR; + simple_ogg_page__clear(&page); + return; + } + + for(i = 0, p = page.body + FLAC__STREAM_METADATA_HEADER_LENGTH; i < encoder->private_->seek_table->num_points; i++, p += 18) { + FLAC__uint64 xx; + unsigned x; + xx = encoder->private_->seek_table->points[i].sample_number; + b[7] = (FLAC__byte)xx; xx >>= 8; + b[6] = (FLAC__byte)xx; xx >>= 8; + b[5] = (FLAC__byte)xx; xx >>= 8; + b[4] = (FLAC__byte)xx; xx >>= 8; + b[3] = (FLAC__byte)xx; xx >>= 8; + b[2] = (FLAC__byte)xx; xx >>= 8; + b[1] = (FLAC__byte)xx; xx >>= 8; + b[0] = (FLAC__byte)xx; xx >>= 8; + xx = encoder->private_->seek_table->points[i].stream_offset; + b[15] = (FLAC__byte)xx; xx >>= 8; + b[14] = (FLAC__byte)xx; xx >>= 8; + b[13] = (FLAC__byte)xx; xx >>= 8; + b[12] = (FLAC__byte)xx; xx >>= 8; + b[11] = (FLAC__byte)xx; xx >>= 8; + b[10] = (FLAC__byte)xx; xx >>= 8; + b[9] = (FLAC__byte)xx; xx >>= 8; + b[8] = (FLAC__byte)xx; xx >>= 8; + x = encoder->private_->seek_table->points[i].frame_samples; + b[17] = (FLAC__byte)x; x >>= 8; + b[16] = (FLAC__byte)x; x >>= 8; + if(encoder->private_->write_callback((FLAC__StreamEncoder*)encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR; + simple_ogg_page__clear(&page); + return; + } + memcpy(p, b, 18); + } + + if(!simple_ogg_page__set_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) { + simple_ogg_page__clear(&page); + return; /* state already set */ + } + simple_ogg_page__clear(&page); + } + + if(encoder->private_->metadata_callback) + encoder->private_->metadata_callback((FLAC__StreamEncoder*)encoder, metadata, client_data); +} + +OggFLAC__StreamEncoderReadStatus file_read_callback_(const OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + (void)client_data; + + *bytes = (unsigned)fread(buffer, 1, *bytes, encoder->private_->file); + if (*bytes == 0) { + if (feof(encoder->private_->file)) + return OggFLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM; + else if (ferror(encoder->private_->file)) + return OggFLAC__STREAM_ENCODER_READ_STATUS_ABORT; + } + return OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE; +} + +FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *super, FLAC__uint64 absolute_byte_offset, void *client_data) +{ + OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super; + + (void)client_data; + + if(fseeko(encoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) + return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR; + else + return FLAC__STREAM_ENCODER_SEEK_STATUS_OK; +} + +FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *super, FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super; + off_t offset; + + (void)client_data; + + offset = ftello(encoder->private_->file); + + if(offset < 0) { + return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR; + } + else { + *absolute_byte_offset = (FLAC__uint64)offset; + return FLAC__STREAM_ENCODER_TELL_STATUS_OK; + } +} + +#ifdef FLAC__VALGRIND_TESTING +static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t ret = fwrite(ptr, size, nmemb, stream); + if(!ferror(stream)) + fflush(stream); + return ret; +} +#else +#define local__fwrite fwrite +#endif + +FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *super, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) +{ + OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super; + + (void)client_data; + + if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, encoder->private_->file) == bytes) { + encoder->private_->bytes_written += bytes; + encoder->private_->samples_written += samples; + /* we keep a high watermark on the number of frames written because + * when the encoder goes back to write metadata, 'current_frame' + * will drop back to 0. + */ + encoder->private_->frames_written = max(encoder->private_->frames_written, current_frame+1); + /*@@@ We would like to add an '&& samples > 0' to the if + * clause here but currently because of the nature of our Ogg + * writing implementation, 'samples' is always 0 (see + * ogg_encoder_aspect.c). The downside is extra progress + * callbacks. + */ + if(0 != encoder->private_->progress_callback /*@@@ && samples > 0 */) + encoder->private_->progress_callback((FLAC__StreamEncoder*)encoder, encoder->private_->bytes_written, encoder->private_->samples_written, encoder->private_->frames_written, encoder->private_->total_frames_estimate, encoder->private_->client_data); + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; + } + else + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; +} + +/* + * This will forcibly set stdout to binary mode (for OSes that require it) + */ +FILE *get_binary_stdout_() +{ + /* if something breaks here it is probably due to the presence or + * absence of an underscore before the identifiers 'setmode', + * 'fileno', and/or 'O_BINARY'; check your system header files. + */ +#if defined _MSC_VER || defined __MINGW32__ + _setmode(_fileno(stdout), _O_BINARY); +#elif defined __CYGWIN__ + /* almost certainly not needed for any modern Cygwin, but let's be safe... */ + setmode(_fileno(stdout), _O_BINARY); +#elif defined __EMX__ + setmode(fileno(stdout), O_BINARY); +#endif - encoder->private_->metadata_callback(encoder, metadata, encoder->private_->client_data); + return stdout; } |