revamp OggFLAC__SeekableStreamDecoder to derive from OggFLAC__StreamDecoder instead of FLAC__SeekableStreamDecoder; rewrite seek routine to do a binary search through Ogg pages, instead of the seektable-based search of FLAC__SeekableStreamDecoder
diff --git a/include/OggFLAC++/decoder.h b/include/OggFLAC++/decoder.h
index 9a4085d..3979aed 100644
--- a/include/OggFLAC++/decoder.h
+++ b/include/OggFLAC++/decoder.h
@@ -209,7 +209,7 @@
 			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 @@
 
 			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 @@
 #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 @@
 
 			State get_state() const;
 			OggFLAC::Decoder::SeekableStream::State get_seekable_stream_decoder_state() const;
-			FLAC::Decoder::SeekableStream::State get_FLAC_seekable_stream_decoder_state() const;
+			OggFLAC::Decoder::Stream::State get_stream_decoder_state() const;
 			FLAC::Decoder::Stream::State get_FLAC_stream_decoder_state() const;
 			bool get_md5_checking() const;
 			unsigned get_channels() const;
diff --git a/include/OggFLAC/file_decoder.h b/include/OggFLAC/file_decoder.h
index 19167dd..cd3c737 100644
--- a/include/OggFLAC/file_decoder.h
+++ b/include/OggFLAC/file_decoder.h
@@ -118,7 +118,7 @@
 
 /***********************************************************************
  *
- * class OggFLAC__FileDecoder : public FLAC__FileDecoder
+ * class OggFLAC__FileDecoder : public OggFLAC__SeekableStreamDecoder
  *
  ***********************************************************************/
 
@@ -421,27 +421,27 @@
  */
 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_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 @@
  *    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_file(OggFLAC__FileDecoder *decoder);
 
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_seek_absolute().
+/** This is inherited from OggFLAC__SeekableStreamDecoder; see
+ *  OggFLAC__seekable_stream_decoder_seek_absolute().
  *
  * \param  decoder  A decoder instance.
  * \param  sample   The target sample number to seek to.
diff --git a/include/OggFLAC/seekable_stream_decoder.h b/include/OggFLAC/seekable_stream_decoder.h
index 496e11f..23a8066 100644
--- a/include/OggFLAC/seekable_stream_decoder.h
+++ b/include/OggFLAC/seekable_stream_decoder.h
@@ -33,8 +33,7 @@
 #define OggFLAC__SEEKABLE_STREAM_DECODER_H
 
 #include "export.h"
-
-#include "FLAC/seekable_stream_decoder.h"
+#include "stream_decoder.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -77,22 +76,27 @@
 	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 @@
 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 @@
  * \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 @@
  * \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 @@
  * \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 @@
  * \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 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 @@
 
 /** 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_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 @@
  *    \c true if successful, \c false if there was an error from
  *    the 'tell' callback.
  */
+/*@@@@@@ probably does not work... is it used? */
 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_decode_position(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *position);
+#endif
 
 /** Initialize the decoder instance.
  *  Should be called after OggFLAC__seekable_stream_decoder_new() and
diff --git a/src/libOggFLAC++/file_decoder.cpp b/src/libOggFLAC++/file_decoder.cpp
index a93d970..25b3e89 100644
--- a/src/libOggFLAC++/file_decoder.cpp
+++ b/src/libOggFLAC++/file_decoder.cpp
@@ -123,10 +123,10 @@
 			return OggFLAC::Decoder::SeekableStream::State(::OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder_));
 		}
 
-		FLAC::Decoder::SeekableStream::State File::get_FLAC_seekable_stream_decoder_state() const
+		OggFLAC::Decoder::Stream::State File::get_stream_decoder_state() const
 		{
 			FLAC__ASSERT(is_valid());
-			return FLAC::Decoder::SeekableStream::State(::OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder_));
+			return OggFLAC::Decoder::Stream::State(::OggFLAC__file_decoder_get_stream_decoder_state(decoder_));
 		}
 
 		FLAC::Decoder::Stream::State File::get_FLAC_stream_decoder_state() const
diff --git a/src/libOggFLAC++/seekable_stream_decoder.cpp b/src/libOggFLAC++/seekable_stream_decoder.cpp
index c98f337..4ad5ddc 100644
--- a/src/libOggFLAC++/seekable_stream_decoder.cpp
+++ b/src/libOggFLAC++/seekable_stream_decoder.cpp
@@ -111,10 +111,10 @@
 			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 @@
 			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 @@
 			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 @@
 			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 @@
 			return instance->tell_callback(absolute_byte_offset);
 		}
 
-		::FLAC__SeekableStreamDecoderLengthStatus SeekableStream::length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
+		::OggFLAC__SeekableStreamDecoderLengthStatus SeekableStream::length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
 		{
 			(void) decoder;
 			FLAC__ASSERT(0 != client_data);
diff --git a/src/libOggFLAC/file_decoder.c b/src/libOggFLAC/file_decoder.c
index 393ac2d..2e9ee12 100644
--- a/src/libOggFLAC/file_decoder.c
+++ b/src/libOggFLAC/file_decoder.c
@@ -52,10 +52,10 @@
 
 static void set_defaults_(OggFLAC__FileDecoder *decoder);
 static FILE *get_binary_stdin_();
-static FLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-static FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-static FLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-static FLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
+static OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+static OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+static OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
 static FLAC__bool eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data);
 static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
 static void metadata_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
@@ -392,11 +392,11 @@
 	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 @@
 	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 @@
 	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 @@
 	if(*bytes > 0) {
 		*bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, file_decoder->private_->file);
 		if(ferror(file_decoder->private_->file)) {
-			return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
+			return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
 		}
 		else {
-			return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
+			return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
 		}
 	}
 	else
-		return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
+		return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
 }
 
-FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
 {
 	OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
 	(void)decoder;
 
 	if(fseek(file_decoder->private_->file, (long)absolute_byte_offset, SEEK_SET) < 0)
-		return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
+		return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
 	else
-		return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
+		return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
 }
 
-FLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
 {
 	OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
 	long pos;
 	(void)decoder;
 
 	if((pos = ftell(file_decoder->private_->file)) < 0)
-		return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
+		return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
 	else {
 		*absolute_byte_offset = (FLAC__uint64)pos;
-		return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
+		return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
 	}
 }
 
-FLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
+OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
 {
 	OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
 	struct stat filestats;
 	(void)decoder;
 
 	if(0 == file_decoder->private_->filename || stat(file_decoder->private_->filename, &filestats) != 0)
-		return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
+		return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
 	else {
 		*stream_length = (FLAC__uint64)filestats.st_size;
-		return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
+		return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
 	}
 }
 
diff --git a/src/libOggFLAC/include/protected/seekable_stream_decoder.h b/src/libOggFLAC/include/protected/seekable_stream_decoder.h
index a434551..2edca15 100644
--- a/src/libOggFLAC/include/protected/seekable_stream_decoder.h
+++ b/src/libOggFLAC/include/protected/seekable_stream_decoder.h
@@ -36,6 +36,7 @@
 #include "private/ogg_decoder_aspect.h"
 
 typedef struct OggFLAC__SeekableStreamDecoderProtected {
+	FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */
 	OggFLAC__SeekableStreamDecoderState state;
 	OggFLAC__OggDecoderAspect ogg_decoder_aspect;
 } OggFLAC__SeekableStreamDecoderProtected;
diff --git a/src/libOggFLAC/seekable_stream_decoder.c b/src/libOggFLAC/seekable_stream_decoder.c
index f7f777c..c405b68 100644
--- a/src/libOggFLAC/seekable_stream_decoder.c
+++ b/src/libOggFLAC/seekable_stream_decoder.c
@@ -29,9 +29,13 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <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 */
 
 /***********************************************************************
  *
@@ -40,16 +44,11 @@
  ***********************************************************************/
 
 static void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder);
-static FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-static FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-static FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-static FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
-static FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data);
-static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-static void metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void error_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-static OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-
+static FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+static void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
 
 /***********************************************************************
  *
@@ -67,7 +66,19 @@
 	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 @@
 
 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 @@
 		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 @@
 	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 @@
 	if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
 		return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED;
 
-	if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
+	if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback)
 		return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
 
-	if(!OggFLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect))
-		return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OGG_ERROR;
+	if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
+		return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
 
-	FLAC__seekable_stream_decoder_set_read_callback(decoder->private_->FLAC_seekable_stream_decoder, read_callback_);
-	FLAC__seekable_stream_decoder_set_seek_callback(decoder->private_->FLAC_seekable_stream_decoder, seek_callback_);
-	FLAC__seekable_stream_decoder_set_tell_callback(decoder->private_->FLAC_seekable_stream_decoder, tell_callback_);
-	FLAC__seekable_stream_decoder_set_length_callback(decoder->private_->FLAC_seekable_stream_decoder, length_callback_);
-	FLAC__seekable_stream_decoder_set_eof_callback(decoder->private_->FLAC_seekable_stream_decoder, eof_callback_);
-	FLAC__seekable_stream_decoder_set_write_callback(decoder->private_->FLAC_seekable_stream_decoder, write_callback_);
-	FLAC__seekable_stream_decoder_set_metadata_callback(decoder->private_->FLAC_seekable_stream_decoder, metadata_callback_);
-	FLAC__seekable_stream_decoder_set_error_callback(decoder->private_->FLAC_seekable_stream_decoder, error_callback_);
-	FLAC__seekable_stream_decoder_set_client_data(decoder->private_->FLAC_seekable_stream_decoder, decoder);
+	decoder->private_->seek_table = 0;
 
-	if(FLAC__seekable_stream_decoder_init(decoder->private_->FLAC_seekable_stream_decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK)
-		return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR;
+	decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
+
+	/* We initialize the MD5Context even though we may never use it.  This is
+	 * because md5 checking may be turned on to start and then turned off if a
+	 * seek occurs.  So we always init the context here and finalize it in
+	 * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
+	 * cleaned up properly.
+	 */
+	MD5Init(&decoder->private_->md5context);
+
+	OggFLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
+	OggFLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
+	OggFLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
+	OggFLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
+	OggFLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder);
+
+	/* We always want to see these blocks.  Whether or not we pass them up
+	 * through the metadata callback will be determined by flags set in our
+	 * implementation of ..._set_metadata_respond/ignore...()
+	 */
+	OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO);
+	OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
+
+	if(OggFLAC__stream_decoder_init(decoder->private_->stream_decoder) != OggFLAC__STREAM_DECODER_OK)
+		return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
 
 	return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
 }
 
 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__SeekableStreamDecoder *decoder)
 {
-	FLAC__bool ok;
+	FLAC__bool md5_failed = false;
 
 	FLAC__ASSERT(0 != decoder);
 	FLAC__ASSERT(0 != decoder->private_);
@@ -193,27 +243,35 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 
 	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 @@
 	decoder->private_->metadata_callback = 0;
 	decoder->private_->error_callback = 0;
 	decoder->private_->client_data = 0;
-	OggFLAC__ogg_decoder_aspect_set_defaults(&decoder->protected_->ogg_decoder_aspect);
+	/* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */
+	decoder->private_->ignore_stream_info_block = false;
+	decoder->private_->ignore_seek_table_block = true;
+
+	decoder->protected_->md5_checking = false;
 }
 
-FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
 {
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-
-	(void)unused;
-
-	switch(OggFLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder, decoder->private_->client_data)) {
-		case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK:
-			return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-		/* we don't really have a way to handle lost sync via read
-		 * callback so we'll let it pass and let the underlying
-		 * FLAC decoder catch the error
-		 */
-		case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC:
-			return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-		case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM:
-			return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-		case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT:
-		case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR:
-			decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
-			return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-		case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR:
-			decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
-			return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-		default:
-			FLAC__ASSERT(0);
-			/* double protection */
-			return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
+	OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
+	(void)decoder;
+	if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
+		*bytes = 0;
+#if 0
+@@@@@@ verify that this is not needed:
+		seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
+#endif
+		return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
 	}
-}
-
-FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 absolute_byte_offset, void *client_data)
-{
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-	(void)unused;
-
-	/* need to flush the Ogg state */
-	OggFLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect);
-
-	return decoder->private_->seek_callback(decoder, absolute_byte_offset, decoder->private_->client_data);
-}
-
-FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 *absolute_byte_offset, void *client_data)
-{
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-	(void)unused;
-	return decoder->private_->tell_callback(decoder, absolute_byte_offset, decoder->private_->client_data);
-}
-
-FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__uint64 *stream_length, void *client_data)
-{
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-	(void)unused;
-	return decoder->private_->length_callback(decoder, stream_length, decoder->private_->client_data);
-}
-
-FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *unused, void *client_data)
-{
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-	(void)unused;
-	return decoder->private_->eof_callback(decoder, decoder->private_->client_data);
-}
-
-FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *unused, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-	(void)unused;
-	return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data);
-}
-
-void metadata_callback_(const FLAC__SeekableStreamDecoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-	(void)unused;
-	decoder->private_->metadata_callback(decoder, metadata, decoder->private_->client_data);
-}
-
-void error_callback_(const FLAC__SeekableStreamDecoder *unused, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)client_data;
-	(void)unused;
-	decoder->private_->error_callback(decoder, status, decoder->private_->client_data);
-}
-
-OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-{
-	OggFLAC__SeekableStreamDecoder *decoder = (OggFLAC__SeekableStreamDecoder*)void_decoder;
-
-	switch(decoder->private_->read_callback(decoder, buffer, bytes, client_data)) {
-		case FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK:
-			if (*bytes == 0)
-				return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM;
+	else if(*bytes > 0) {
+		if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) {
+			seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
+			return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+		}
+		if(*bytes == 0) {
+			if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
+#if 0
+@@@@@@ verify that this is not needed:
+				seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
+#endif
+				return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+			}
 			else
-				return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK;
-		case FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR:
-			return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
-		default:
-			/* double protection: */
-			FLAC__ASSERT(0);
-			return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
+				return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+		}
+		else {
+			return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+		}
 	}
+	else
+		return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
+}
+
+FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+{
+	OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
+	(void)decoder;
+
+	if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
+		FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
+		FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
+		FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;
+
+		FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
+
+		seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */
+		if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
+			unsigned delta = (unsigned)(target_sample - this_frame_sample);
+			/* kick out of seek mode */
+			seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
+			/* shift out the samples before target_sample */
+			if(delta > 0) {
+				unsigned channel;
+				const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
+				for(channel = 0; channel < frame->header.channels; channel++)
+					newbuffer[channel] = buffer[channel] + delta;
+				seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;
+				seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
+				/* write the relevant samples */
+				return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);
+			}
+			else {
+				/* write the relevant samples */
+				return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
+			}
+		}
+		else {
+			return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+		}
+	}
+	else {
+		if(seekable_stream_decoder->private_->do_md5_checking) {
+			if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
+				return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+		}
+		return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
+	}
+}
+
+void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+	OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
+	(void)decoder;
+
+	if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
+		seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
+		/* save the MD5 signature for comparison later */
+		memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
+		if(0 == memcmp(seekable_stream_decoder->private_->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
+			seekable_stream_decoder->private_->do_md5_checking = false;
+	}
+	else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
+		seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;
+	}
+
+	if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
+		FLAC__bool ignore_block = false;
+		if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)
+			ignore_block = true;
+		else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)
+			ignore_block = true;
+		if(!ignore_block)
+			seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);
+	}
+}
+
+void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+	OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
+	(void)decoder;
+
+	if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)
+		seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
+}
+
+FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
+{
+	FLAC__uint64 left_pos = 0, right_pos = stream_length;
+	FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;
+	unsigned iteration = 0;
+
+	/* In the first iterations, we will calculate the target byte position 
+	 * by the distance from the target sample to left_sample and
+	 * right_sample.  After that, we will switch to binary search.
+	 */
+	static const unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
+
+	/* We will switch to a linear search once our current sample is less
+	 * that this number of samples ahead of the target sample
+	 */
+	static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
+
+	/* If the total number of samples is unknown, use a large value and
+	 * increase 'iteration' to force binary search immediately.
+	 */
+	if(right_sample == 0) {
+		right_sample = (FLAC__uint64)(-1);
+		iteration = BINARY_SEARCH_AFTER_ITERATION;
+	}
+
+	decoder->private_->target_sample = target_sample;
+	for( ; ; iteration++) {
+		if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
+			decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
+			return false;
+		}
+		/* our write callback will change the state when it gets to the target frame */
+		if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
+			break;
+		}
+		else {
+			const FLAC__uint64 this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
+			FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
+
+			if (this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
+				FLAC__uint64 pos;
+
+				if (iteration >= BINARY_SEARCH_AFTER_ITERATION)
+					pos = (right_pos + left_pos) / 2;
+				else
+					pos = (FLAC__uint64)((double)(target_sample - left_sample) / (double)(right_pos - left_pos));
+
+				if (this_frame_sample <= target_sample) {
+					/* The 'equal' case should not happen, since
+					 * OggFLAC__stream_decoder_process_single()
+					 * should recognize that it has hit the
+					 * target sample and we would exit through
+					 * the 'break' above.
+					 */
+					FLAC__ASSERT(this_frame_sample != target_sample);
+
+					left_sample = this_frame_sample;
+					left_pos = pos;
+				}
+				else if(this_frame_sample > target_sample) {
+					right_sample = this_frame_sample;
+					right_pos = pos;
+				}
+
+				/* physical seek */
+				if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
+					decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
+					return false;
+				}
+				if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
+					decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
+					return false;
+				}
+			}
+		}
+	}
+
+	return true;
 }
diff --git a/src/test_libOggFLAC++/decoders.cpp b/src/test_libOggFLAC++/decoders.cpp
index c2baae2..874515b 100644
--- a/src/test_libOggFLAC++/decoders.cpp
+++ b/src/test_libOggFLAC++/decoders.cpp
@@ -802,10 +802,10 @@
 	~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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	OggFLAC::Decoder::SeekableStream::State state_ = decoder->get_seekable_stream_decoder_state();
 	printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state_), state_.as_cstring());
 
-	printf("testing get_FLAC_seekable_stream_decoder_state()... ");
-	FLAC::Decoder::SeekableStream::State state__ = decoder->get_FLAC_seekable_stream_decoder_state();
-	printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state__), state__.as_cstring());
+	printf("testing get_stream_decoder_state()... ");
+	OggFLAC::Decoder::Stream::State state__ = decoder->get_stream_decoder_state();
+	printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__StreamDecoderState)state__), state__.as_cstring());
 
 	printf("testing get_FLAC_stream_decoder_state()... ");
 	FLAC::Decoder::Stream::State state___ = decoder->get_FLAC_stream_decoder_state();
diff --git a/src/test_libOggFLAC/decoders.c b/src/test_libOggFLAC/decoders.c
index fbcc1bf..f5e144a 100644
--- a/src/test_libOggFLAC/decoders.c
+++ b/src/test_libOggFLAC/decoders.c
@@ -79,10 +79,10 @@
 		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 @@
 	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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 
 	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 @@
 {
 	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 @@
 	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 @@
 {
 	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 @@
 	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);