diff --git a/include/OggFLAC++/decoder.h b/include/OggFLAC++/decoder.h index 9a4085d7..3979aed2 100644 --- a/include/OggFLAC++/decoder.h +++ b/include/OggFLAC++/decoder.h @@ -209,7 +209,7 @@ namespace OggFLAC { bool set_metadata_ignore_all(); State get_state() const; - FLAC::Decoder::SeekableStream::State get_FLAC_seekable_stream_decoder_state() const; + OggFLAC::Decoder::Stream::State get_stream_decoder_state() const; FLAC::Decoder::Stream::State get_FLAC_stream_decoder_state() const; bool get_md5_checking() const; unsigned get_channels() const; @@ -231,10 +231,10 @@ namespace OggFLAC { bool seek_absolute(FLAC__uint64 sample); protected: - virtual ::FLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0; - virtual ::FLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) = 0; - virtual ::FLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) = 0; - virtual ::FLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length) = 0; + virtual ::OggFLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0; + virtual ::OggFLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) = 0; + virtual ::OggFLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) = 0; + virtual ::OggFLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length) = 0; virtual bool eof_callback() = 0; virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0; virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0; @@ -246,10 +246,10 @@ namespace OggFLAC { #endif ::OggFLAC__SeekableStreamDecoder *decoder_; private: - static ::FLAC__SeekableStreamDecoderReadStatus read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); - static ::FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); - static ::FLAC__SeekableStreamDecoderTellStatus tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); - static ::FLAC__SeekableStreamDecoderLengthStatus length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); + 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); @@ -311,7 +311,7 @@ namespace OggFLAC { State get_state() const; OggFLAC::Decoder::SeekableStream::State get_seekable_stream_decoder_state() const; - FLAC::Decoder::SeekableStream::State get_FLAC_seekable_stream_decoder_state() const; + OggFLAC::Decoder::Stream::State get_stream_decoder_state() const; FLAC::Decoder::Stream::State get_FLAC_stream_decoder_state() const; bool get_md5_checking() const; unsigned get_channels() const; diff --git a/include/OggFLAC/file_decoder.h b/include/OggFLAC/file_decoder.h index 19167dd0..cd3c737f 100644 --- a/include/OggFLAC/file_decoder.h +++ b/include/OggFLAC/file_decoder.h @@ -118,7 +118,7 @@ extern OggFLAC_API const char * const OggFLAC__FileDecoderStateString[]; /*********************************************************************** * - * class OggFLAC__FileDecoder : public FLAC__FileDecoder + * class OggFLAC__FileDecoder : public OggFLAC__SeekableStreamDecoder * ***********************************************************************/ @@ -421,27 +421,27 @@ OggFLAC_API OggFLAC__FileDecoderState OggFLAC__file_decoder_get_state(const OggF */ OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_seekable_stream_decoder_state(const OggFLAC__FileDecoder *decoder); -/** Get the state of the underlying FLAC seekable stream decoder. +/** Get the state of the underlying stream decoder. * Useful when the file decoder state is * \c OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR * and the seekable stream decoder state is - * \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR. + * \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR. * * \param decoder A decoder instance to query. * \assert * \code decoder != NULL \endcode - * \retval FLAC__SeekableStreamDecoderState - * The FLAC seekable stream decoder state. + * \retval OggFLAC__StreamDecoderState + * The stream decoder state. */ -OggFLAC_API FLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(const OggFLAC__FileDecoder *decoder); +OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__file_decoder_get_stream_decoder_state(const OggFLAC__FileDecoder *decoder); /** Get the state of the underlying FLAC stream decoder. * Useful when the file decoder state is * \c OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR * and the seekable stream decoder state is - * \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR - * and the * FLAC seekable stream decoder state is - * \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR. + * \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR + * and the stream decoder state is + * \c OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR. * * \param decoder A decoder instance to query. * \assert @@ -530,6 +530,8 @@ OggFLAC_API unsigned OggFLAC__file_decoder_get_sample_rate(const OggFLAC__FileDe */ OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDecoder *decoder); +#if 0 +@@@@@@ this can never be made to work without writing a custom Ogg decoder; remove for release /** This is inherited from FLAC__FileDecoder; see * FLAC__file_decoder_get_decode_position(). * @@ -543,6 +545,7 @@ OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDeco * the 'tell' callback. */ OggFLAC_API FLAC__bool OggFLAC__file_decoder_get_decode_position(const OggFLAC__FileDecoder *decoder, FLAC__uint64 *position); +#endif /** Initialize the decoder instance. * Should be called after OggFLAC__file_decoder_new() and @@ -614,8 +617,8 @@ OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_metadata(OggFL */ OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_file(OggFLAC__FileDecoder *decoder); -/** This is inherited from FLAC__FileDecoder; see - * FLAC__file_decoder_seek_absolute(). +/** This is inherited from OggFLAC__SeekableStreamDecoder; see + * OggFLAC__seekable_stream_decoder_seek_absolute(). * * \param decoder A decoder instance. * \param sample The target sample number to seek to. diff --git a/include/OggFLAC/seekable_stream_decoder.h b/include/OggFLAC/seekable_stream_decoder.h index 496e11f2..23a80667 100644 --- a/include/OggFLAC/seekable_stream_decoder.h +++ b/include/OggFLAC/seekable_stream_decoder.h @@ -33,8 +33,7 @@ #define OggFLAC__SEEKABLE_STREAM_DECODER_H #include "export.h" - -#include "FLAC/seekable_stream_decoder.h" +#include "stream_decoder.h" #ifdef __cplusplus extern "C" { @@ -77,22 +76,27 @@ typedef enum { OggFLAC__SEEKABLE_STREAM_DECODER_OK = 0, /**< The decoder is in the normal OK state. */ + OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING, + /**< The decoder is in the process of seeking. */ + OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM, /**< The decoder has reached the end of the stream. */ - OggFLAC__SEEKABLE_STREAM_DECODER_OGG_ERROR, - /**< An error occurred in the underlying Ogg layer. */ + OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR, + /**< Memory allocation failed. */ - OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR, - /**< An error occurred in the underlying FLAC seekable stream decoder; - * check OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(). + OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR, + /**< An error occurred in the underlying stream decoder; + * check OggFLAC__seekable_stream_decoder_get_stream_decoder_state(). */ OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR, /**< The read callback returned an error. */ - OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR, - /**< Memory allocation failed. */ + OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR, + /**< An error occurred while seeking or the seek or tell + * callback returned an error. + */ OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED, /**< OggFLAC__seekable_stream_decoder_init() was called when the decoder was @@ -116,6 +120,86 @@ typedef enum { extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderStateString[]; +/** Return values for the OggFLAC__SeekableStreamDecoder read callback. + */ +typedef enum { + + OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK, + /**< The read was OK and decoding can continue. */ + + OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + +} OggFLAC__SeekableStreamDecoderReadStatus; + +/** Maps a OggFLAC__SeekableStreamDecoderReadStatus to a C string. + * + * Using a OggFLAC__SeekableStreamDecoderReadStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderReadStatusString[]; + + +/** Return values for the OggFLAC__SeekableStreamDecoder seek callback. + */ +typedef enum { + + OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK, + /**< The seek was OK and decoding can continue. */ + + OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + +} OggFLAC__SeekableStreamDecoderSeekStatus; + +/** Maps a OggFLAC__SeekableStreamDecoderSeekStatus to a C string. + * + * Using a OggFLAC__SeekableStreamDecoderSeekStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderSeekStatusString[]; + + +/** Return values for the OggFLAC__SeekableStreamDecoder tell callback. + */ +typedef enum { + + OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK, + /**< The tell was OK and decoding can continue. */ + + OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + +} OggFLAC__SeekableStreamDecoderTellStatus; + +/** Maps a OggFLAC__SeekableStreamDecoderTellStatus to a C string. + * + * Using a OggFLAC__SeekableStreamDecoderTellStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderTellStatusString[]; + + +/** Return values for the OggFLAC__SeekableStreamDecoder length callback. + */ +typedef enum { + + OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK, + /**< The length call was OK and decoding can continue. */ + + OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + +} OggFLAC__SeekableStreamDecoderLengthStatus; + +/** Maps a OggFLAC__SeekableStreamDecoderLengthStatus to a C string. + * + * Using a OggFLAC__SeekableStreamDecoderLengthStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderLengthStatusString[]; + + /*********************************************************************** * * class OggFLAC__SeekableStreamDecoder : public FLAC__StreamDecoder @@ -147,7 +231,7 @@ typedef struct { * \retval FLAC__SeekableStreamDecoderReadStatus * The callee's return status. */ -typedef FLAC__SeekableStreamDecoderReadStatus (*OggFLAC__SeekableStreamDecoderReadCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +typedef OggFLAC__SeekableStreamDecoderReadStatus (*OggFLAC__SeekableStreamDecoderReadCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); /** Signature for the seek callback. * See OggFLAC__seekable_stream_decoder_set_seek_callback() for more info. @@ -160,7 +244,7 @@ typedef FLAC__SeekableStreamDecoderReadStatus (*OggFLAC__SeekableStreamDecoderRe * \retval FLAC__SeekableStreamDecoderSeekStatus * The callee's return status. */ -typedef FLAC__SeekableStreamDecoderSeekStatus (*OggFLAC__SeekableStreamDecoderSeekCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); +typedef OggFLAC__SeekableStreamDecoderSeekStatus (*OggFLAC__SeekableStreamDecoderSeekCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); /** Signature for the tell callback. * See OggFLAC__seekable_stream_decoder_set_tell_callback() for more info. @@ -173,7 +257,7 @@ typedef FLAC__SeekableStreamDecoderSeekStatus (*OggFLAC__SeekableStreamDecoderSe * \retval FLAC__SeekableStreamDecoderTellStatus * The callee's return status. */ -typedef FLAC__SeekableStreamDecoderTellStatus (*OggFLAC__SeekableStreamDecoderTellCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); +typedef OggFLAC__SeekableStreamDecoderTellStatus (*OggFLAC__SeekableStreamDecoderTellCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); /** Signature for the length callback. * See OggFLAC__seekable_stream_decoder_set_length_callback() for more info. @@ -186,7 +270,7 @@ typedef FLAC__SeekableStreamDecoderTellStatus (*OggFLAC__SeekableStreamDecoderTe * \retval FLAC__SeekableStreamDecoderLengthStatus * The callee's return status. */ -typedef FLAC__SeekableStreamDecoderLengthStatus (*OggFLAC__SeekableStreamDecoderLengthCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); +typedef OggFLAC__SeekableStreamDecoderLengthStatus (*OggFLAC__SeekableStreamDecoderLengthCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); /** Signature for the EOF callback. * See OggFLAC__seekable_stream_decoder_set_eof_callback() for more info. @@ -550,22 +634,22 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all( */ OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder); -/** Get the state of the underlying FLAC seekable stream decoder. +/** Get the state of the underlying stream decoder. * Useful when the seekable stream decoder state is - * \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR. + * \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR. * * \param decoder A decoder instance to query. * \assert * \code decoder != NULL \endcode - * \retval FLAC__SeekableStreamDecoderState - * The FLAC seekable stream decoder state. + * \retval OggFLAC__StreamDecoderState + * The stream decoder state. */ -OggFLAC_API FLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder); +OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder); -/** Get the state of the underlying FLAC seekable stream decoder's stream decoder. +/** Get the state of the underlying stream decoder's FLAC stream decoder. * Useful when the seekable stream decoder state is - * \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR and the - * FLAC seekable stream decoder state is \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR + * \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR and the + * stream decoder state is \c OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR * * \param decoder A decoder instance to query. * \assert @@ -577,8 +661,8 @@ OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_s /** Get the current decoder state as a C string. * This version automatically resolves - * \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR - * by getting the FLAC seekable stream decoder's state. + * \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR + * by getting the stream decoder's state. * * \param decoder A decoder instance to query. * \assert @@ -654,6 +738,8 @@ OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggF */ OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder); +#if 0 +@@@@@@ this can never be made to work without writing a custom Ogg decoder; remove for release /** Returns the decoder's current read position within the stream. * This is inherited from FLAC__SeekableStreamDecoder; see * FLAC__seekable_stream_decoder_get_decode_position(). @@ -667,7 +753,9 @@ OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLA * \c true if successful, \c false if there was an error from * the 'tell' callback. */ +/*@@@@@@ probably does not work... is it used? */ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_decode_position(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *position); +#endif /** Initialize the decoder instance. * Should be called after OggFLAC__seekable_stream_decoder_new() and diff --git a/src/libOggFLAC++/file_decoder.cpp b/src/libOggFLAC++/file_decoder.cpp index a93d970a..25b3e89f 100644 --- a/src/libOggFLAC++/file_decoder.cpp +++ b/src/libOggFLAC++/file_decoder.cpp @@ -123,10 +123,10 @@ namespace OggFLAC { return OggFLAC::Decoder::SeekableStream::State(::OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder_)); } - FLAC::Decoder::SeekableStream::State File::get_FLAC_seekable_stream_decoder_state() const + OggFLAC::Decoder::Stream::State File::get_stream_decoder_state() const { FLAC__ASSERT(is_valid()); - return FLAC::Decoder::SeekableStream::State(::OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder_)); + return OggFLAC::Decoder::Stream::State(::OggFLAC__file_decoder_get_stream_decoder_state(decoder_)); } FLAC::Decoder::Stream::State File::get_FLAC_stream_decoder_state() const diff --git a/src/libOggFLAC++/seekable_stream_decoder.cpp b/src/libOggFLAC++/seekable_stream_decoder.cpp index c98f3377..4ad5ddc9 100644 --- a/src/libOggFLAC++/seekable_stream_decoder.cpp +++ b/src/libOggFLAC++/seekable_stream_decoder.cpp @@ -111,10 +111,10 @@ namespace OggFLAC { return State(::OggFLAC__seekable_stream_decoder_get_state(decoder_)); } - FLAC::Decoder::SeekableStream::State SeekableStream::get_FLAC_seekable_stream_decoder_state() const + OggFLAC::Decoder::Stream::State SeekableStream::get_stream_decoder_state() const { FLAC__ASSERT(is_valid()); - return FLAC::Decoder::SeekableStream::State(::OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder_)); + return OggFLAC::Decoder::Stream::State(::OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder_)); } FLAC::Decoder::Stream::State SeekableStream::get_FLAC_stream_decoder_state() const @@ -216,7 +216,7 @@ namespace OggFLAC { return (bool)::OggFLAC__seekable_stream_decoder_seek_absolute(decoder_, sample); } - ::FLAC__SeekableStreamDecoderReadStatus SeekableStream::read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) + ::OggFLAC__SeekableStreamDecoderReadStatus SeekableStream::read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) { (void) decoder; FLAC__ASSERT(0 != client_data); @@ -225,7 +225,7 @@ namespace OggFLAC { return instance->read_callback(buffer, bytes); } - ::FLAC__SeekableStreamDecoderSeekStatus SeekableStream::seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) + ::OggFLAC__SeekableStreamDecoderSeekStatus SeekableStream::seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) { (void) decoder; FLAC__ASSERT(0 != client_data); @@ -234,7 +234,7 @@ namespace OggFLAC { return instance->seek_callback(absolute_byte_offset); } - ::FLAC__SeekableStreamDecoderTellStatus SeekableStream::tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) + ::OggFLAC__SeekableStreamDecoderTellStatus SeekableStream::tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) { (void) decoder; FLAC__ASSERT(0 != client_data); @@ -243,7 +243,7 @@ namespace OggFLAC { return instance->tell_callback(absolute_byte_offset); } - ::FLAC__SeekableStreamDecoderLengthStatus SeekableStream::length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) + ::OggFLAC__SeekableStreamDecoderLengthStatus SeekableStream::length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) { (void) decoder; FLAC__ASSERT(0 != client_data); diff --git a/src/libOggFLAC/file_decoder.c b/src/libOggFLAC/file_decoder.c index 393ac2d3..2e9ee129 100644 --- a/src/libOggFLAC/file_decoder.c +++ b/src/libOggFLAC/file_decoder.c @@ -52,10 +52,10 @@ static void set_defaults_(OggFLAC__FileDecoder *decoder); static FILE *get_binary_stdin_(); -static FLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); -static FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); -static FLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); -static FLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); +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); @@ -392,11 +392,11 @@ OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_seekab return OggFLAC__seekable_stream_decoder_get_state(decoder->private_->seekable_stream_decoder); } -OggFLAC_API FLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(const OggFLAC__FileDecoder *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_FLAC_seekable_stream_decoder_state(decoder->private_->seekable_stream_decoder); + 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) @@ -456,12 +456,15 @@ OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDeco return OggFLAC__seekable_stream_decoder_get_blocksize(decoder->private_->seekable_stream_decoder); } +#if 0 +@@@@@@ this can never be made to work without writing a custom Ogg decoder; remove for release OggFLAC_API FLAC__bool OggFLAC__file_decoder_get_decode_position(const OggFLAC__FileDecoder *decoder, FLAC__uint64 *position) { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); return OggFLAC__seekable_stream_decoder_get_decode_position(decoder->private_->seekable_stream_decoder, position); } +#endif OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_single(OggFLAC__FileDecoder *decoder) { @@ -581,7 +584,7 @@ FILE *get_binary_stdin_() return stdin; } -FLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) +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; @@ -589,52 +592,52 @@ FLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStre if(*bytes > 0) { *bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, file_decoder->private_->file); if(ferror(file_decoder->private_->file)) { - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; } else { - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; + return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; } } else - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */ + return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */ } -FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) +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(fseek(file_decoder->private_->file, (long)absolute_byte_offset, SEEK_SET) < 0) - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; else - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; + return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; } -FLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) +OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) { OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data; long pos; (void)decoder; if((pos = ftell(file_decoder->private_->file)) < 0) - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; else { *absolute_byte_offset = (FLAC__uint64)pos; - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; + return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; } } -FLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) +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 FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; else { *stream_length = (FLAC__uint64)filestats.st_size; - return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; + return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; } } diff --git a/src/libOggFLAC/include/protected/seekable_stream_decoder.h b/src/libOggFLAC/include/protected/seekable_stream_decoder.h index a4345516..2edca150 100644 --- a/src/libOggFLAC/include/protected/seekable_stream_decoder.h +++ b/src/libOggFLAC/include/protected/seekable_stream_decoder.h @@ -36,6 +36,7 @@ #include "private/ogg_decoder_aspect.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__OggDecoderAspect ogg_decoder_aspect; } OggFLAC__SeekableStreamDecoderProtected; diff --git a/src/libOggFLAC/seekable_stream_decoder.c b/src/libOggFLAC/seekable_stream_decoder.c index f7f777c9..c405b689 100644 --- a/src/libOggFLAC/seekable_stream_decoder.c +++ b/src/libOggFLAC/seekable_stream_decoder.c @@ -29,9 +29,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include /* for calloc() */ +#include /* for memcpy()/memcmp() */ #include "FLAC/assert.h" #include "protected/seekable_stream_decoder.h" +#include "protected/stream_decoder.h" +#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 */ /*********************************************************************** * @@ -40,16 +44,11 @@ ***********************************************************************/ static void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder); -static FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); -static FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); -static FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); -static FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); -static FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data); -static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); -static void metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); -static void error_callback_(const FLAC__SeekableStreamDecoder *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__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); /*********************************************************************** * @@ -67,7 +66,19 @@ typedef struct OggFLAC__SeekableStreamDecoderPrivate { OggFLAC__SeekableStreamDecoderMetadataCallback metadata_callback; OggFLAC__SeekableStreamDecoderErrorCallback error_callback; void *client_data; - FLAC__SeekableStreamDecoder *FLAC_seekable_stream_decoder; + OggFLAC__StreamDecoder *stream_decoder; + FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */ + struct 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; } OggFLAC__SeekableStreamDecoderPrivate; /*********************************************************************** @@ -78,26 +89,50 @@ typedef struct OggFLAC__SeekableStreamDecoderPrivate { 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_OGG_ERROR", - "OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR", - "OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR", "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; @@ -116,8 +151,8 @@ OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new return 0; } - decoder->private_->FLAC_seekable_stream_decoder = FLAC__seekable_stream_decoder_new(); - if(0 == decoder->private_->FLAC_seekable_stream_decoder) { + decoder->private_->stream_decoder = OggFLAC__stream_decoder_new(); + if(0 == decoder->private_->stream_decoder) { free(decoder->private_); free(decoder->protected_); free(decoder); @@ -136,11 +171,11 @@ OggFLAC_API void OggFLAC__seekable_stream_decoder_delete(OggFLAC__SeekableStream FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->protected_); FLAC__ASSERT(0 != decoder->private_); - FLAC__ASSERT(0 != decoder->private_->FLAC_seekable_stream_decoder); + FLAC__ASSERT(0 != decoder->private_->stream_decoder); - OggFLAC__seekable_stream_decoder_finish(decoder); + (void)OggFLAC__seekable_stream_decoder_finish(decoder); - FLAC__seekable_stream_decoder_delete(decoder->private_->FLAC_seekable_stream_decoder); + OggFLAC__stream_decoder_delete(decoder->private_->stream_decoder); free(decoder->private_); free(decoder->protected_); @@ -160,31 +195,46 @@ OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_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 || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback) + 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(!OggFLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect)) - return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OGG_ERROR; + 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; - FLAC__seekable_stream_decoder_set_read_callback(decoder->private_->FLAC_seekable_stream_decoder, read_callback_); - FLAC__seekable_stream_decoder_set_seek_callback(decoder->private_->FLAC_seekable_stream_decoder, seek_callback_); - FLAC__seekable_stream_decoder_set_tell_callback(decoder->private_->FLAC_seekable_stream_decoder, tell_callback_); - FLAC__seekable_stream_decoder_set_length_callback(decoder->private_->FLAC_seekable_stream_decoder, length_callback_); - FLAC__seekable_stream_decoder_set_eof_callback(decoder->private_->FLAC_seekable_stream_decoder, eof_callback_); - FLAC__seekable_stream_decoder_set_write_callback(decoder->private_->FLAC_seekable_stream_decoder, write_callback_); - FLAC__seekable_stream_decoder_set_metadata_callback(decoder->private_->FLAC_seekable_stream_decoder, metadata_callback_); - FLAC__seekable_stream_decoder_set_error_callback(decoder->private_->FLAC_seekable_stream_decoder, error_callback_); - FLAC__seekable_stream_decoder_set_client_data(decoder->private_->FLAC_seekable_stream_decoder, decoder); + decoder->private_->seek_table = 0; - if(FLAC__seekable_stream_decoder_init(decoder->private_->FLAC_seekable_stream_decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) - return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR; + decoder->private_->do_md5_checking = decoder->protected_->md5_checking; + + /* We initialize the 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. + */ + 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 ok; + FLAC__bool md5_failed = false; FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); @@ -193,27 +243,35 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__Seekable if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) return true; - FLAC__ASSERT(0 != decoder->private_->FLAC_seekable_stream_decoder); + FLAC__ASSERT(0 != decoder->private_->stream_decoder); - ok = FLAC__seekable_stream_decoder_finish(decoder->private_->FLAC_seekable_stream_decoder); + /* see the comment in OggFLAC__seekable_stream_decoder_init() as to why we + * always call MD5Final() + */ + MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context); - OggFLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect); + 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 ok; + 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->private_); FLAC__ASSERT(0 != decoder->protected_); if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) return false; - return FLAC__seekable_stream_decoder_set_md5_checking(decoder->private_->FLAC_seekable_stream_decoder, value); + decoder->protected_->md5_checking = value; + return true; } OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_read_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderReadCallback value) @@ -331,9 +389,14 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond(Ogg 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 FLAC__seekable_stream_decoder_set_metadata_respond(decoder->private_->FLAC_seekable_stream_decoder, type); + 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]) @@ -341,9 +404,10 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_app 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 FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder->private_->FLAC_seekable_stream_decoder, id); + 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) @@ -351,9 +415,12 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all 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 FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder->private_->FLAC_seekable_stream_decoder); + 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) @@ -361,9 +428,19 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggF 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 FLAC__seekable_stream_decoder_set_metadata_ignore(decoder->private_->FLAC_seekable_stream_decoder, type); + 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]) @@ -371,9 +448,10 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_appl 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 FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder->private_->FLAC_seekable_stream_decoder, id); + 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) @@ -381,9 +459,15 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all( 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 FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder->private_->FLAC_seekable_stream_decoder); + 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) @@ -393,76 +477,85 @@ OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder return decoder->protected_->state; } -OggFLAC_API FLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder) +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 FLAC__seekable_stream_decoder_get_state(decoder->private_->FLAC_seekable_stream_decoder); + 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 FLAC__seekable_stream_decoder_get_stream_decoder_state(decoder->private_->FLAC_seekable_stream_decoder); + 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_FLAC_SEEKABLE_STREAM_DECODER_ERROR) + if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) return OggFLAC__SeekableStreamDecoderStateString[decoder->protected_->state]; else - return FLAC__seekable_stream_decoder_get_resolved_state_string(decoder->private_->FLAC_seekable_stream_decoder); + 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->private_); - return FLAC__seekable_stream_decoder_get_md5_checking(decoder->private_->FLAC_seekable_stream_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 FLAC__seekable_stream_decoder_get_channels(decoder->private_->FLAC_seekable_stream_decoder); + 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 FLAC__seekable_stream_decoder_get_channel_assignment(decoder->private_->FLAC_seekable_stream_decoder); + 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 FLAC__seekable_stream_decoder_get_bits_per_sample(decoder->private_->FLAC_seekable_stream_decoder); + 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 FLAC__seekable_stream_decoder_get_sample_rate(decoder->private_->FLAC_seekable_stream_decoder); + 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 FLAC__seekable_stream_decoder_get_blocksize(decoder->private_->FLAC_seekable_stream_decoder); + return OggFLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder); } +#if 0 +@@@@@@ this can never be made to work without writing a custom Ogg decoder; remove for release OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_decode_position(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *position) { FLAC__ASSERT(0 != decoder); FLAC__ASSERT(0 != decoder->private_); - return FLAC__seekable_stream_decoder_get_decode_position(decoder->private_->FLAC_seekable_stream_decoder, position); + FLAC__ASSERT(0 != position); + + if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) + return false; + FLAC__ASSERT(*position >= OggFLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder)); + *position -= OggFLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder); + return true; } +#endif OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableStreamDecoder *decoder) { @@ -470,10 +563,10 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableS FLAC__ASSERT(0 != decoder->private_); FLAC__ASSERT(0 != decoder->protected_); - OggFLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect); + decoder->private_->do_md5_checking = false; - if(!FLAC__seekable_stream_decoder_flush(decoder->private_->FLAC_seekable_stream_decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR; + if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) { + decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; return false; } @@ -489,15 +582,27 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_reset(OggFLAC__SeekableS FLAC__ASSERT(0 != decoder->protected_); if(!OggFLAC__seekable_stream_decoder_flush(decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; return false; } - if(!FLAC__seekable_stream_decoder_reset(decoder->private_->FLAC_seekable_stream_decoder)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR; + 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 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. + */ + MD5Init(&decoder->private_->md5context); + decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK; return true; @@ -508,7 +613,7 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__ FLAC__bool ret; FLAC__ASSERT(0 != decoder); - if(FLAC__seekable_stream_decoder_get_state(decoder->private_->FLAC_seekable_stream_decoder) == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) + 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) @@ -516,9 +621,9 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__ FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK); - ret = FLAC__seekable_stream_decoder_process_single(decoder->private_->FLAC_seekable_stream_decoder); + ret = OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder); if(!ret) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR; + decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; return ret; } @@ -528,7 +633,7 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_met FLAC__bool ret; FLAC__ASSERT(0 != decoder); - if(FLAC__seekable_stream_decoder_get_state(decoder->private_->FLAC_seekable_stream_decoder) == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) + 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) @@ -536,9 +641,9 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_met FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK); - ret = FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder->private_->FLAC_seekable_stream_decoder); + ret = OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder); if(!ret) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR; + decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; return ret; } @@ -548,7 +653,7 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_str FLAC__bool ret; FLAC__ASSERT(0 != decoder); - if(FLAC__seekable_stream_decoder_get_state(decoder->private_->FLAC_seekable_stream_decoder) == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) + 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) @@ -556,28 +661,50 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_str FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK); - ret = FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder->private_->FLAC_seekable_stream_decoder); + ret = OggFLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder); if(!ret) - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR; + 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); - if(!FLAC__seekable_stream_decoder_seek_absolute(decoder->private_->FLAC_seekable_stream_decoder, sample)) { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR; + 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; } - else { - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK; - return true; + /* 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); +} /*********************************************************************** * @@ -596,108 +723,207 @@ void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder) decoder->private_->metadata_callback = 0; decoder->private_->error_callback = 0; decoder->private_->client_data = 0; - OggFLAC__ogg_decoder_aspect_set_defaults(&decoder->protected_->ogg_decoder_aspect); + /* 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__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__byte buffer[], unsigned *bytes, void *client_data) +FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) { - OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data; - - (void)unused; - - 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: - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; - /* we don't really have a way to handle lost sync via read - * callback so we'll let it pass and let the underlying - * FLAC decoder catch the error - */ - case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC: - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; - case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM: - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; - case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT: - case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR: - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR; - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; - case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR: - decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; - default: - FLAC__ASSERT(0); - /* double protection */ - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + 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 +@@@@@@ verify that this is not needed: + seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; +#endif + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; } -} - -FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 absolute_byte_offset, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data; - (void)unused; - - /* need to flush the Ogg state */ - OggFLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect); - - return decoder->private_->seek_callback(decoder, absolute_byte_offset, decoder->private_->client_data); -} - -FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 *absolute_byte_offset, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data; - (void)unused; - return decoder->private_->tell_callback(decoder, absolute_byte_offset, decoder->private_->client_data); -} - -FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 *stream_length, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data; - (void)unused; - return decoder->private_->length_callback(decoder, stream_length, decoder->private_->client_data); -} - -FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *unused, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data; - (void)unused; - return decoder->private_->eof_callback(decoder, decoder->private_->client_data); -} - -FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *unused, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) -{ - OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data; - (void)unused; - return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data); -} - -void metadata_callback_(const FLAC__SeekableStreamDecoder *unused, const FLAC__StreamMetadata *metadata, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data; - (void)unused; - decoder->private_->metadata_callback(decoder, metadata, decoder->private_->client_data); -} - -void error_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__StreamDecoderErrorStatus status, void *client_data) -{ - OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)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__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)void_decoder; - - switch(decoder->private_->read_callback(decoder, buffer, bytes, client_data)) { - case FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK: - if (*bytes == 0) - return OggFLAC__OGG_DECODER_ASPECT_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 +@@@@@@ verify that this is not needed: + seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; +#endif + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } else - return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK; - case FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR: - return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT; - default: - /* double protection: */ - FLAC__ASSERT(0); - return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT; + 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_->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; + 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. After that, we will switch to binary search. + */ + static const 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); + iteration = BINARY_SEARCH_AFTER_ITERATION; + } + + decoder->private_->target_sample = target_sample; + for( ; ; iteration++) { + if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) { + 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 */ + if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) { + break; + } + else { + const FLAC__uint64 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 (this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) { + FLAC__uint64 pos; + + if (iteration >= BINARY_SEARCH_AFTER_ITERATION) + pos = (right_pos + left_pos) / 2; + else + pos = (FLAC__uint64)((double)(target_sample - left_sample) / (double)(right_pos - left_pos)); + + 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; + left_pos = pos; + } + else if(this_frame_sample > target_sample) { + right_sample = this_frame_sample; + right_pos = pos; + } + + /* 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; + } + } + } + } + + return true; +} diff --git a/src/test_libOggFLAC++/decoders.cpp b/src/test_libOggFLAC++/decoders.cpp index c2baae21..874515b6 100644 --- a/src/test_libOggFLAC++/decoders.cpp +++ b/src/test_libOggFLAC++/decoders.cpp @@ -802,10 +802,10 @@ public: ~SeekableStreamDecoder() { } // from OggFLAC::Decoder::SeekableStream - ::FLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes); - ::FLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset); - ::FLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset); - ::FLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length); + ::OggFLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes); + ::OggFLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset); + ::OggFLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset); + ::OggFLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length); bool eof_callback(); ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]); void metadata_callback(const ::FLAC__StreamMetadata *metadata); @@ -816,56 +816,56 @@ public: bool test_respond(); }; -::FLAC__SeekableStreamDecoderReadStatus SeekableStreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes) +::OggFLAC__SeekableStreamDecoderReadStatus SeekableStreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes) { switch(common_read_callback_(buffer, bytes)) { case ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE: case ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM: - return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; case ::FLAC__STREAM_DECODER_READ_STATUS_ABORT: - return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; default: FLAC__ASSERT(0); - return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; } } -::FLAC__SeekableStreamDecoderSeekStatus SeekableStreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset) +::OggFLAC__SeekableStreamDecoderSeekStatus SeekableStreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset) { if(error_occurred_) - return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; if(::fseek(file_, (long)absolute_byte_offset, SEEK_SET) < 0) { error_occurred_ = true; - return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; } - return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; } -::FLAC__SeekableStreamDecoderTellStatus SeekableStreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset) +::OggFLAC__SeekableStreamDecoderTellStatus SeekableStreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset) { if(error_occurred_) - return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; long offset = ::ftell(file_); *absolute_byte_offset = (FLAC__uint64)offset; if(offset < 0) { error_occurred_ = true; - return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; } - return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; } -::FLAC__SeekableStreamDecoderLengthStatus SeekableStreamDecoder::length_callback(FLAC__uint64 *stream_length) +::OggFLAC__SeekableStreamDecoderLengthStatus SeekableStreamDecoder::length_callback(FLAC__uint64 *stream_length) { if(error_occurred_) - return ::FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; *stream_length = (FLAC__uint64)oggflacfilesize_; - return ::FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; + return ::OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; } bool SeekableStreamDecoder::eof_callback() @@ -903,10 +903,10 @@ bool SeekableStreamDecoder::die(const char *msg) const printf("FAILED"); printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state), state.as_cstring()); - if(state == ::OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) { - FLAC::Decoder::SeekableStream::State state_ = get_FLAC_seekable_stream_decoder_state(); - printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state_), state_.as_cstring()); - if(state_ == ::FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + if(state == ::OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + OggFLAC::Decoder::Stream::State state_ = get_stream_decoder_state(); + printf(" stream decoder state = %u (%s)\n", (unsigned)((::OggFLAC__StreamDecoderState)state_), state_.as_cstring()); + if(state_ == ::OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) { FLAC::Decoder::Stream::State state__ = get_FLAC_stream_decoder_state(); printf(" FLAC stream decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state__), state__.as_cstring()); } @@ -1046,9 +1046,9 @@ static bool test_seekable_stream_decoder() OggFLAC::Decoder::SeekableStream::State state = decoder->get_state(); printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state), state.as_cstring()); - printf("testing get_FLAC_seekable_stream_decoder_state()... "); - FLAC::Decoder::SeekableStream::State state_ = decoder->get_FLAC_seekable_stream_decoder_state(); - printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state_), state_.as_cstring()); + printf("testing get_stream_decoder_state()... "); + OggFLAC::Decoder::Stream::State state_ = decoder->get_stream_decoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__StreamDecoderState)state_), state_.as_cstring()); printf("testing get_FLAC_stream_decoder_state()... "); FLAC::Decoder::Stream::State state__ = decoder->get_FLAC_stream_decoder_state(); @@ -1575,10 +1575,10 @@ bool FileDecoder::die(const char *msg) const if(state == ::OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) { OggFLAC::Decoder::SeekableStream::State state_ = get_seekable_stream_decoder_state(); printf(" seekable stream decoder state = %u (%s)\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state_), state_.as_cstring()); - if(state_ == ::OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) { - FLAC::Decoder::SeekableStream::State state__ = get_FLAC_seekable_stream_decoder_state(); - printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state__), state__.as_cstring()); - if(state__ == ::FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + if(state_ == ::OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + OggFLAC::Decoder::Stream::State state__ = get_stream_decoder_state(); + printf(" stream decoder state = %u (%s)\n", (unsigned)((::OggFLAC__StreamDecoderState)state__), state__.as_cstring()); + if(state__ == ::OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) { FLAC::Decoder::Stream::State state___ = get_FLAC_stream_decoder_state(); printf(" FLAC stream decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state___), state___.as_cstring()); } @@ -1730,9 +1730,9 @@ static bool test_file_decoder() OggFLAC::Decoder::SeekableStream::State state_ = decoder->get_seekable_stream_decoder_state(); printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state_), state_.as_cstring()); - printf("testing get_FLAC_seekable_stream_decoder_state()... "); - FLAC::Decoder::SeekableStream::State state__ = decoder->get_FLAC_seekable_stream_decoder_state(); - printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state__), state__.as_cstring()); + printf("testing get_stream_decoder_state()... "); + OggFLAC::Decoder::Stream::State state__ = decoder->get_stream_decoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__StreamDecoderState)state__), state__.as_cstring()); printf("testing get_FLAC_stream_decoder_state()... "); FLAC::Decoder::Stream::State state___ = decoder->get_FLAC_stream_decoder_state(); diff --git a/src/test_libOggFLAC/decoders.c b/src/test_libOggFLAC/decoders.c index fbcc1bf7..f5e144a6 100644 --- a/src/test_libOggFLAC/decoders.c +++ b/src/test_libOggFLAC/decoders.c @@ -79,10 +79,10 @@ static FLAC__bool die_ss_(const char *msg, const OggFLAC__SeekableStreamDecoder printf("FAILED"); printf(", state = %u (%s)\n", (unsigned)state, OggFLAC__SeekableStreamDecoderStateString[state]); - if(state == OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) { - FLAC__SeekableStreamDecoderState state_ = OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder); - printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)state_, FLAC__SeekableStreamDecoderStateString[state_]); - if(state_ == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + if(state == OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + OggFLAC__StreamDecoderState state_ = OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder); + printf(" stream decoder state = %u (%s)\n", (unsigned)state_, OggFLAC__StreamDecoderStateString[state_]); + if(state_ == OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) { FLAC__StreamDecoderState state__ = OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(decoder); printf(" FLAC stream decoder state = %u (%s)\n", (unsigned)state__, FLAC__StreamDecoderStateString[state__]); } @@ -104,10 +104,10 @@ static FLAC__bool die_f_(const char *msg, const OggFLAC__FileDecoder *decoder) if(state == OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) { OggFLAC__SeekableStreamDecoderState state_ = OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder); printf(" seekable stream decoder state = %u (%s)\n", (unsigned)state_, OggFLAC__SeekableStreamDecoderStateString[state_]); - if(state_ == OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) { - FLAC__SeekableStreamDecoderState state__ = OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder); - printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)state__, FLAC__SeekableStreamDecoderStateString[state__]); - if(state__ == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + if(state_ == OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + OggFLAC__StreamDecoderState state__ = OggFLAC__file_decoder_get_stream_decoder_state(decoder); + printf(" stream decoder state = %u (%s)\n", (unsigned)state__, OggFLAC__StreamDecoderStateString[state__]); + if(state__ == OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) { FLAC__StreamDecoderState state___ = OggFLAC__file_decoder_get_FLAC_stream_decoder_state(decoder); printf(" FLAC stream decoder state = %u (%s)\n", (unsigned)state___, FLAC__StreamDecoderStateString[state___]); } @@ -801,22 +801,22 @@ static FLAC__bool test_stream_decoder() return true; } -static FLAC__SeekableStreamDecoderReadStatus seekable_stream_decoder_read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) +static OggFLAC__SeekableStreamDecoderReadStatus seekable_stream_decoder_read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) { (void)decoder; switch(stream_decoder_read_callback_(0, buffer, bytes, client_data)) { case FLAC__STREAM_DECODER_READ_STATUS_CONTINUE: case FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM: - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; + return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; case FLAC__STREAM_DECODER_READ_STATUS_ABORT: - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; default: FLAC__ASSERT(0); - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; } } -static FLAC__SeekableStreamDecoderSeekStatus seekable_stream_decoder_seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) +static OggFLAC__SeekableStreamDecoderSeekStatus seekable_stream_decoder_seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) { seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data; @@ -824,21 +824,21 @@ static FLAC__SeekableStreamDecoderSeekStatus seekable_stream_decoder_seek_callba if(0 == dcd) { printf("ERROR: client_data in seek callback is NULL\n"); - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; } if(dcd->error_occurred) - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; if(fseek(dcd->file, (long)absolute_byte_offset, SEEK_SET) < 0) { dcd->error_occurred = true; - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; } - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; + return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; } -static FLAC__SeekableStreamDecoderTellStatus seekable_stream_decoder_tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) +static OggFLAC__SeekableStreamDecoderTellStatus seekable_stream_decoder_tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) { seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data; long offset; @@ -847,24 +847,24 @@ static FLAC__SeekableStreamDecoderTellStatus seekable_stream_decoder_tell_callba if(0 == dcd) { printf("ERROR: client_data in tell callback is NULL\n"); - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; } if(dcd->error_occurred) - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; offset = ftell(dcd->file); *absolute_byte_offset = (FLAC__uint64)offset; if(offset < 0) { dcd->error_occurred = true; - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; } - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; + return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; } -static FLAC__SeekableStreamDecoderLengthStatus seekable_stream_decoder_length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) +static OggFLAC__SeekableStreamDecoderLengthStatus seekable_stream_decoder_length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) { seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data; @@ -872,14 +872,14 @@ static FLAC__SeekableStreamDecoderLengthStatus seekable_stream_decoder_length_ca if(0 == dcd) { printf("ERROR: client_data in length callback is NULL\n"); - return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; } if(dcd->error_occurred) - return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; + return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR; *stream_length = (FLAC__uint64)oggflacfilesize_; - return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; + return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; } static FLAC__bool seekable_stream_decoder_eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data) @@ -977,7 +977,7 @@ static FLAC__bool test_seekable_stream_decoder() { OggFLAC__SeekableStreamDecoder *decoder; OggFLAC__SeekableStreamDecoderState state; - FLAC__SeekableStreamDecoderState fsstate; + OggFLAC__StreamDecoderState sstate; FLAC__StreamDecoderState fstate; seekable_stream_decoder_client_data_struct decoder_client_data; @@ -1087,9 +1087,9 @@ static FLAC__bool test_seekable_stream_decoder() state = OggFLAC__seekable_stream_decoder_get_state(decoder); printf("returned state = %u (%s)... OK\n", state, OggFLAC__SeekableStreamDecoderStateString[state]); - printf("testing OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state()... "); - fsstate = OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder); - printf("returned state = %u (%s)... OK\n", fsstate, FLAC__SeekableStreamDecoderStateString[fsstate]); + printf("testing OggFLAC__seekable_stream_decoder_get_stream_decoder_state()... "); + sstate = OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder); + printf("returned state = %u (%s)... OK\n", sstate, OggFLAC__StreamDecoderStateString[sstate]); printf("testing OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state()... "); fstate = OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(decoder); @@ -1581,8 +1581,8 @@ static FLAC__bool test_file_decoder() { OggFLAC__FileDecoder *decoder; OggFLAC__FileDecoderState state; - OggFLAC__SeekableStreamDecoderState sstate; - FLAC__SeekableStreamDecoderState fsstate; + OggFLAC__SeekableStreamDecoderState ssstate; + OggFLAC__StreamDecoderState sstate; FLAC__StreamDecoderState fstate; seekable_stream_decoder_client_data_struct decoder_client_data; @@ -1673,12 +1673,12 @@ static FLAC__bool test_file_decoder() printf("returned state = %u (%s)... OK\n", state, OggFLAC__FileDecoderStateString[state]); printf("testing OggFLAC__file_decoder_get_seekable_stream_decoder_state()... "); - sstate = OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder); - printf("returned state = %u (%s)... OK\n", sstate, OggFLAC__SeekableStreamDecoderStateString[sstate]); + ssstate = OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder); + printf("returned state = %u (%s)... OK\n", ssstate, OggFLAC__SeekableStreamDecoderStateString[ssstate]); - printf("testing OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state()... "); - fsstate = OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder); - printf("returned state = %u (%s)... OK\n", fsstate, FLAC__SeekableStreamDecoderStateString[fsstate]); + printf("testing OggFLAC__file_decoder_get_stream_decoder_state()... "); + sstate = OggFLAC__file_decoder_get_stream_decoder_state(decoder); + printf("returned state = %u (%s)... OK\n", sstate, OggFLAC__StreamDecoderStateString[sstate]); printf("testing OggFLAC__file_decoder_get_FLAC_stream_decoder_state()... "); fstate = OggFLAC__file_decoder_get_FLAC_stream_decoder_state(decoder);