revamp OggFLAC__SeekableStreamDecoder to derive from OggFLAC__StreamDecoder instead...
authorJosh Coalson <jcoalson@users.sourceforce.net>
Wed, 7 Jul 2004 07:35:02 +0000 (07:35 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Wed, 7 Jul 2004 07:35:02 +0000 (07:35 +0000)
include/OggFLAC++/decoder.h
include/OggFLAC/file_decoder.h
include/OggFLAC/seekable_stream_decoder.h
src/libOggFLAC++/file_decoder.cpp
src/libOggFLAC++/seekable_stream_decoder.cpp
src/libOggFLAC/file_decoder.c
src/libOggFLAC/include/protected/seekable_stream_decoder.h
src/libOggFLAC/seekable_stream_decoder.c
src/test_libOggFLAC++/decoders.cpp
src/test_libOggFLAC/decoders.c

index 9a4085d..3979aed 100644 (file)
@@ -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;
index 19167dd..cd3c737 100644 (file)
@@ -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.
index 496e11f..23a8066 100644 (file)
@@ -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
index a93d970..25b3e89 100644 (file)
@@ -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
index c98f337..4ad5ddc 100644 (file)
@@ -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);
index 393ac2d..2e9ee12 100644 (file)
 
 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;
        }
 }
 
index a434551..2edca15 100644 (file)
@@ -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;
index f7f777c..c405b68 100644 (file)
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdio.h>
 #include <stdlib.h> /* for calloc() */
+#include <string.h> /* for memcpy()/memcmp() */
 #include "FLAC/assert.h"
 #include "protected/seekable_stream_decoder.h"
+#include "protected/stream_decoder.h"
+#include "../libFLAC/include/private/md5.h" /* @@@@@@ ugly hack, but how else to do?  we need to reuse the md5 code but don't want to expose it */
 
 /***********************************************************************
  *
  ***********************************************************************/
 
 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(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;
 
-       if(!OggFLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect))
-               return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OGG_ERROR;
+       decoder->private_->seek_table = 0;
 
-       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_->do_md5_checking = decoder->protected_->md5_checking;
 
-       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;
+       /* 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);
-}
-
-FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *unused, 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;
-       }
-}
-
-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);
+       /* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */
+       decoder->private_->ignore_stream_info_block = false;
+       decoder->private_->ignore_seek_table_block = true;
 
-       return decoder->private_->seek_callback(decoder, absolute_byte_offset, decoder->private_->client_data);
+       decoder->protected_->md5_checking = false;
 }
 
-FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 *absolute_byte_offset, 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;
-       return decoder->private_->tell_callback(decoder, absolute_byte_offset, decoder->private_->client_data);
+       OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
+       (void)decoder;
+       if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
+               *bytes = 0;
+#if 0
+@@@@@@ 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 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 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);
+       }
 }
 
-FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 *stream_length, void *client_data)
+void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
-       OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-       (void)unused;
-       return decoder->private_->length_callback(decoder, stream_length, decoder->private_->client_data);
-}
+       OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
+       (void)decoder;
 
-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);
-}
+       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;
+       }
 
-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);
+       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 metadata_callback_(const FLAC__SeekableStreamDecoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
+void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
-       OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-       (void)unused;
-       decoder->private_->metadata_callback(decoder, metadata, decoder->private_->client_data);
-}
+       OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
+       (void)decoder;
 
-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);
+       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);
 }
 
-OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
 {
-       OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)void_decoder;
+       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;
 
-       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
-                               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;
+       /* 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;
 }
index c2baae2..874515b 100644 (file)
@@ -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();
index fbcc1bf..f5e144a 100644 (file)
@@ -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);