merge down from merged-API-layer branch: cvs -q up -dP -j API_LAYER_MERGING_BASELINE...
authorJosh Coalson <jcoalson@users.sourceforce.net>
Wed, 13 Sep 2006 01:42:27 +0000 (01:42 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Wed, 13 Sep 2006 01:42:27 +0000 (01:42 +0000)
156 files changed:
FLAC.dsw
README
configure.in
doc/html/changelog.html
include/FLAC++/decoder.h
include/FLAC++/encoder.h
include/FLAC/Makefile.am
include/FLAC/all.h
include/FLAC/file_decoder.h [deleted file]
include/FLAC/file_encoder.h [deleted file]
include/FLAC/metadata.h
include/FLAC/seekable_stream_decoder.h [deleted file]
include/FLAC/seekable_stream_encoder.h [deleted file]
include/FLAC/stream_decoder.h
include/FLAC/stream_encoder.h
include/Makefile.am
include/OggFLAC++/decoder.h
include/OggFLAC++/encoder.h
include/OggFLAC/Makefile.am
include/OggFLAC/all.h
include/OggFLAC/file_decoder.h [deleted file]
include/OggFLAC/file_encoder.h [deleted file]
include/OggFLAC/seekable_stream_decoder.h [deleted file]
include/OggFLAC/seekable_stream_encoder.h [deleted file]
include/OggFLAC/stream_decoder.h
include/OggFLAC/stream_encoder.h
include/test_libs_common/Makefile.am [new file with mode: 0644]
include/test_libs_common/file_utils_flac.h [moved from src/test_libFLAC/file_utils.h with 100% similarity]
include/test_libs_common/file_utils_oggflac.h [moved from src/test_libOggFLAC/file_utils.h with 100% similarity]
include/test_libs_common/metadata_utils.h [moved from src/test_libOggFLAC/metadata_utils.h with 100% similarity]
src/Makefile.am
src/Makefile.lite
src/flac/decode.c
src/flac/encode.c
src/flac/main.c
src/libFLAC++/Makefile.am
src/libFLAC++/Makefile.lite
src/libFLAC++/file_decoder.cpp
src/libFLAC++/file_encoder.cpp
src/libFLAC++/libFLAC++_dynamic.dsp
src/libFLAC++/libFLAC++_static.dsp
src/libFLAC++/seekable_stream_decoder.cpp [deleted file]
src/libFLAC++/seekable_stream_encoder.cpp [deleted file]
src/libFLAC++/stream_decoder.cpp
src/libFLAC++/stream_encoder.cpp
src/libFLAC/Makefile.am
src/libFLAC/Makefile.lite
src/libFLAC/file_decoder.c [deleted file]
src/libFLAC/file_encoder.c [deleted file]
src/libFLAC/include/protected/Makefile.am
src/libFLAC/include/protected/all.h
src/libFLAC/include/protected/file_decoder.h [deleted file]
src/libFLAC/include/protected/file_encoder.h [deleted file]
src/libFLAC/include/protected/seekable_stream_decoder.h [deleted file]
src/libFLAC/include/protected/seekable_stream_encoder.h [deleted file]
src/libFLAC/include/protected/stream_decoder.h
src/libFLAC/include/protected/stream_encoder.h
src/libFLAC/libFLAC_dynamic.dsp
src/libFLAC/libFLAC_static.dsp
src/libFLAC/metadata_iterators.c
src/libFLAC/metadata_object.c
src/libFLAC/seekable_stream_decoder.c [deleted file]
src/libFLAC/seekable_stream_encoder.c [deleted file]
src/libFLAC/stream_decoder.c
src/libFLAC/stream_encoder.c
src/libOggFLAC++/Makefile.am
src/libOggFLAC++/Makefile.lite
src/libOggFLAC++/file_decoder.cpp
src/libOggFLAC++/file_encoder.cpp
src/libOggFLAC++/libOggFLAC++_dynamic.dsp
src/libOggFLAC++/libOggFLAC++_static.dsp
src/libOggFLAC++/seekable_stream_decoder.cpp [deleted file]
src/libOggFLAC++/seekable_stream_encoder.cpp [deleted file]
src/libOggFLAC++/stream_decoder.cpp
src/libOggFLAC++/stream_encoder.cpp
src/libOggFLAC/Makefile.am
src/libOggFLAC/Makefile.lite
src/libOggFLAC/file_decoder.c [deleted file]
src/libOggFLAC/file_encoder.c [deleted file]
src/libOggFLAC/include/private/ogg_decoder_aspect.h
src/libOggFLAC/include/private/ogg_helper.h
src/libOggFLAC/include/protected/Makefile.am
src/libOggFLAC/include/protected/all.h
src/libOggFLAC/include/protected/file_decoder.h [deleted file]
src/libOggFLAC/include/protected/file_encoder.h [deleted file]
src/libOggFLAC/include/protected/seekable_stream_decoder.h [deleted file]
src/libOggFLAC/include/protected/seekable_stream_encoder.h [deleted file]
src/libOggFLAC/include/protected/stream_encoder.h
src/libOggFLAC/libOggFLAC_dynamic.dsp
src/libOggFLAC/libOggFLAC_static.dsp
src/libOggFLAC/ogg_decoder_aspect.c
src/libOggFLAC/ogg_encoder_aspect.c
src/libOggFLAC/ogg_helper.c
src/libOggFLAC/seekable_stream_decoder.c [deleted file]
src/libOggFLAC/seekable_stream_encoder.c [deleted file]
src/libOggFLAC/stream_decoder.c
src/libOggFLAC/stream_encoder.c
src/metaflac/operations_shorthand_seektable.c
src/plugin_winamp2/in_flac.c
src/plugin_winamp2/playback.c
src/plugin_winamp2/playback.h
src/plugin_xmms/http.c
src/plugin_xmms/http.h
src/plugin_xmms/plugin.c
src/share/grabbag/replaygain.c
src/share/grabbag/seektable.c
src/test_libFLAC++/Makefile.am
src/test_libFLAC++/Makefile.lite
src/test_libFLAC++/README [deleted file]
src/test_libFLAC++/decoders.cpp
src/test_libFLAC++/encoders.cpp
src/test_libFLAC++/file_utils.h [deleted file]
src/test_libFLAC++/metadata_manip.cpp
src/test_libFLAC++/metadata_utils.c [deleted file]
src/test_libFLAC++/metadata_utils.h [deleted file]
src/test_libFLAC++/test_libFLAC++.dsp
src/test_libFLAC/Makefile.am
src/test_libFLAC/Makefile.lite
src/test_libFLAC/decoders.c
src/test_libFLAC/encoders.c
src/test_libFLAC/file_utils.c [deleted file]
src/test_libFLAC/metadata_manip.c
src/test_libFLAC/metadata_object.c
src/test_libFLAC/metadata_utils.c [deleted file]
src/test_libFLAC/metadata_utils.h [deleted file]
src/test_libFLAC/test_libFLAC.dsp
src/test_libOggFLAC++/Makefile.am
src/test_libOggFLAC++/Makefile.lite
src/test_libOggFLAC++/README [deleted file]
src/test_libOggFLAC++/decoders.cpp
src/test_libOggFLAC++/encoders.cpp
src/test_libOggFLAC++/file_utils.h [deleted file]
src/test_libOggFLAC++/metadata_utils.h [deleted file]
src/test_libOggFLAC++/test_libOggFLAC++.dsp
src/test_libOggFLAC/Makefile.am
src/test_libOggFLAC/Makefile.lite
src/test_libOggFLAC/README [deleted file]
src/test_libOggFLAC/decoders.c
src/test_libOggFLAC/encoders.c
src/test_libOggFLAC/file_utils.c [deleted file]
src/test_libOggFLAC/metadata_utils.c [deleted file]
src/test_libOggFLAC/test_libOggFLAC.dsp
src/test_libs_common/Makefile.am [new file with mode: 0644]
src/test_libs_common/Makefile.lite [new file with mode: 0644]
src/test_libs_common/README [new file with mode: 0644]
src/test_libs_common/file_utils_flac.c [moved from src/test_libFLAC++/file_utils.c with 93% similarity]
src/test_libs_common/file_utils_oggflac.c [moved from src/test_libOggFLAC++/file_utils.c with 88% similarity]
src/test_libs_common/metadata_utils.c [moved from src/test_libOggFLAC++/metadata_utils.c with 99% similarity]
src/test_libs_common/test_libs_common_static.dsp [new file with mode: 0644]
src/test_seeking/main.c
test/cuesheets/Makefile.am
test/flac-to-flac-metadata-test-files/Makefile.am
test/flac-to-flac-metadata-test-files/case03c-expect.meta
test/flac-to-flac-metadata-test-files/case04c-expect.meta
test/metaflac-test-files/case07-expect.meta
test/test_seeking.sh

index 5546a6e..71eccec 100644 (file)
--- a/FLAC.dsw
+++ b/FLAC.dsw
@@ -81,6 +81,9 @@ Package=<4>
     Project_Dep_Name libOggFLAC++_static\r
     End Project Dependency\r
     Begin Project Dependency\r
+    Project_Dep_Name test_libs_common_static\r
+    End Project Dependency\r
+    Begin Project Dependency\r
     Project_Dep_Name plugin_common_static\r
     End Project Dependency\r
     Begin Project Dependency\r
@@ -159,6 +162,9 @@ Package=<4>
     Project_Dep_Name libOggFLAC++_static\r
     End Project Dependency\r
     Begin Project Dependency\r
+    Project_Dep_Name test_libs_common_static\r
+    End Project Dependency\r
+    Begin Project Dependency\r
     Project_Dep_Name plugin_common_static\r
     End Project Dependency\r
     Begin Project Dependency\r
@@ -498,6 +504,24 @@ Package=<4>
 \r
 ###############################################################################\r
 \r
+Project: "test_libs_common"=.\src\test_libs_common\test_libs_common_static.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+    Begin Project Dependency\r
+    Project_Dep_Name libFLAC_static\r
+    End Project Dependency\r
+    Begin Project Dependency\r
+    Project_Dep_Name libOggFLAC_static\r
+    End Project Dependency\r
+}}}\r
+\r
+###############################################################################\r
+\r
 Project: "test_libFLAC"=.\src\test_libFLAC\test_libFLAC.dsp - Package Owner=<4>\r
 \r
 Package=<5>\r
@@ -509,6 +533,9 @@ Package=<4>
     Begin Project Dependency\r
     Project_Dep_Name libFLAC_static\r
     End Project Dependency\r
+    Begin Project Dependency\r
+    Project_Dep_Name test_libs_common_static\r
+    End Project Dependency\r
 }}}\r
 \r
 ###############################################################################\r
@@ -524,6 +551,9 @@ Package=<4>
     Begin Project Dependency\r
     Project_Dep_Name libFLAC++_static\r
     End Project Dependency\r
+    Begin Project Dependency\r
+    Project_Dep_Name test_libs_common_static\r
+    End Project Dependency\r
 }}}\r
 \r
 ###############################################################################\r
@@ -539,6 +569,9 @@ Package=<4>
     Begin Project Dependency\r
     Project_Dep_Name libOggFLAC_static\r
     End Project Dependency\r
+    Begin Project Dependency\r
+    Project_Dep_Name test_libs_common_static\r
+    End Project Dependency\r
 }}}\r
 \r
 ###############################################################################\r
@@ -554,6 +587,9 @@ Package=<4>
     Begin Project Dependency\r
     Project_Dep_Name libOggFLAC++_static\r
     End Project Dependency\r
+    Begin Project Dependency\r
+    Project_Dep_Name test_libs_common_static\r
+    End Project Dependency\r
 }}}\r
 \r
 ###############################################################################\r
diff --git a/README b/README
index 1f9c72a..d3438c4 100644 (file)
--- a/README
+++ b/README
@@ -241,17 +241,18 @@ configure.in and src/libFLAC/Makefile.am; the following dependency
 graph shows which modules may be pruned without breaking things
 further down:
 
-file_encoder.h
-       stream_encoder.h
-               format.h
+stream_encoder.h
+       stream_decoder.h
+       format.h
 
-file_decoder.h
-       seekable_stream_decoder.h
-               stream_decoder.h
-                       format.h
+stream_decoder.h
+       format.h
 
 metadata.h
        format.h
 
+In other words, for pure decoding applications, both the stream encoder
+and metadata editing interfaces can be safely removed.
+
 There is a section dedicated to embedded use in the libFLAC API
 HTML documentation (see doc/html/api/index.html).
index 7dce4e7..30ac4d6 100644 (file)
@@ -314,6 +314,7 @@ AC_CONFIG_FILES([ \
        src/share/utf8/Makefile \
        src/test_grabbag/Makefile \
        src/test_grabbag/cuesheet/Makefile \
+       src/test_libs_common/Makefile \
        src/test_libFLAC/Makefile \
        src/test_libFLAC++/Makefile \
        src/test_libOggFLAC/Makefile \
@@ -327,6 +328,7 @@ AC_CONFIG_FILES([ \
        include/OggFLAC++/Makefile \
        include/share/Makefile \
        include/share/grabbag/Makefile \
+       include/test_libs_common/Makefile \
        doc/Makefile \
        doc/html/Makefile \
        doc/html/images/Makefile \
@@ -334,6 +336,8 @@ AC_CONFIG_FILES([ \
        man/Makefile \
        test/Makefile \
        test/cuesheets/Makefile \
+       test/flac-to-flac-metadata-test-files/Makefile \
+       test/metaflac-test-files/Makefile \
        build/Makefile \
        obj/Makefile \
        obj/debug/Makefile \
index edfaa15..de28f62 100644 (file)
@@ -53,7 +53,7 @@
        </div>
        <div class="box_header"></div>
        <div class="box_body">
-               This is an informal changelog, a summary of changes in each release.  Particulary important for developers is the precise description of changes to the library interfaces.
+               This is an informal changelog, a summary of changes in each release.  Particulary important for developers is the precise description of changes to the library interfaces.  See also the <a href="http://flac.sourceforge.net/api/group__porting.html">porting guide</a> for specific instructions on porting to newer versions of FLAC.
 
                <br /><br />
 
@@ -68,6 +68,7 @@
                                        <li>Large file (&gt;2GB) support everywhere</li>
                                        <li>Much better recovery for corrupted files</li>
                                        <li><span class="commandname">flac</span> now supports FLAC as input to the encoder (i.e. can re-encode FLAC to FLAC) and preserve all the metadata like tags, etc.</li>
+                                       <li>In the developer libraries, the interface has been simplfied by merging the three decoding layers into a single class; ditto for the encoders.</li>
                                </ul>
                        </li>
                        <li>
                                </ul>
                        </li>
                        <li>
-                               Interface changes:
+                               Interface changes (see also the <a href="http://flac.sourceforge.net/api/group__porting__1__1__2__to__1__1__3.html">porting guide</a> for specific instructions on porting to FLAC 1.1.3):
                                <ul>
                                        <li>
+                                               all libraries;
+                                               <ul>
+                                                       <li>Merged seekable stream decoder and file decoder into the stream decoder.</li>
+                                                       <li>Merged seekable stream encoder and file encoder into the stream encoder.</li>
+                                               </ul>
+                                       </li>
+                                       <li>
                                                libFLAC:
                                                <ul>
-                                                       <li><b>Added</b> FLAC__*_encoder_set_apodization()</li>
+                                                       <li><b>Added</b> FLAC__stream_encoder_set_apodization()</li>
                                                        <li><b>Added</b> FLAC__metadata_object_cuesheet_calculate_cddb_id()</li>
                                                        <li><b>Added</b> FLAC__metadata_get_cuesheet()</li>
                                                        <li><b>Changed</b> FLAC__StreamDecoderState: removed state FLAC__STREAM_DECODER_UNPARSEABLE_STREAM</li>
                                        <li>
                                                libFLAC++:
                                                <ul>
-                                                       <li><b>Added</b> FLAC::*::Encoder::set_apodization()</li>
+                                                       <li><b>Added</b> FLAC::Encoder::Stream::set_apodization()</li>
                                                        <li><b>Added</b> FLAC::Metadata::CueSheet::calculate_cddb_id()</li>
                                                        <li><b>Added</b> FLAC::Metadata::get_cuesheet()</li>
                                                </ul>
                                        <li>
                                                libOggFLAC:
                                                <ul>
-                                                       <li><b>Added</b> OggFLAC__*_encoder_set_apodization()</li>
+                                                       <li><b>Added</b> OggFLAC__stream_encoder_set_apodization()</li>
                                                        <li><b>Added</b> OggFLAC__metadata_object_cuesheet_calculate_cddb_id()</li>
                                                        <li><b>Added</b> OggFLAC__metadata_get_cuesheet()</li>
                                                </ul>
                                        <li>
                                                libOggFLAC++:
                                                <ul>
-                                                       <li><b>Added</b> OggFLAC::*::Encoder::set_apodization()</li>
+                                                       <li><b>Added</b> OggFLAC::Encoder::Stream::set_apodization()</li>
                                                        <li><b>Added</b> OggFLAC::Metadata::CueSheet::calculate_cddb_id()</li>
                                                        <li><b>Added</b> OggFLAC::Metadata::get_cuesheet()</li>
                                                </ul>
index aba733f..5143311 100644 (file)
@@ -34,8 +34,7 @@
 
 #include "export.h"
 
-#include "FLAC/file_decoder.h"
-#include "FLAC/seekable_stream_decoder.h"
+#include <string>
 #include "FLAC/stream_decoder.h"
 
 
  *  \ingroup flacpp
  *
  *  \brief
- *  This module describes the three decoder layers provided by libFLAC++.
+ *  This module describes the decoder layers provided by libFLAC++.
  *
  * The libFLAC++ decoder classes are object wrappers around their
- * counterparts in libFLAC.  All three decoding layers available in
+ * counterparts in libFLAC.  All decoding layers available in
  * libFLAC are also provided here.  The interface is very similar;
  * make sure to read the \link flac_decoder libFLAC decoder module \endlink.
  *
- * The only real difference here is that instead of passing in C function
- * pointers for callbacks, you inherit from the decoder class and provide
- * implementations for the callbacks in the derived class; because of this
- * there is no need for a 'client_data' property.
+ * There are only two significant differences here.  First, instead of
+ * passing in C function pointers for callbacks, you inherit from the
+ * decoder class and provide implementations for the callbacks in your
+ * derived class; because of this there is no need for a 'client_data'
+ * property.
+ *
+ * Second, there are two stream decoder classes.  FLAC::Decoder::Stream
+ * is used for the same cases that FLAC__stream_decoder_init_stream() is
+ * used, and FLAC::Decoder::File is used for the same cases that
+ * FLAC__stream_decoder_init_FILE() and FLAC__stream_decoder_init_file()
+ * are used.
  */
 
 namespace FLAC {
        namespace Decoder {
 
-               // ============================================================
-               //
-               //  Equivalent: FLAC__StreamDecoder
-               //
-               // ============================================================
-
                /** \defgroup flacpp_stream_decoder FLAC++/decoder.h: stream decoder class
                 *  \ingroup flacpp_decoder
                 *
                 *  \brief
                 *  This class wraps the ::FLAC__StreamDecoder.
                 *
-                * See the \link flac_stream_decoder libFLAC stream decoder module \endlink.
+                * See the \link flac_stream_decoder libFLAC stream decoder module \endlink
+                * for basic usage.
                 *
                 * \{
                 */
 
-               /** This class wraps the ::FLAC__StreamDecoder.
+               /** This class wraps the ::FLAC__StreamDecoder.  If you are
+                *  decoding from a file, FLAC::Decoder::File may be more
+                *  convenient.
+                *
+                * The usage of this class is similar to FLAC__StreamDecoder,
+                * except instead of providing callbacks to
+                * FLAC__stream_decoder_init_stream(), you will inherit from this
+                * class and override the virtual callback functions with your
+                * own implementations, then call Stream::init().  The rest of
+                * the calls work the same as in the C layer.
+                *
+                * Only the read, write, and error callbacks are mandatory.  The
+                * others are optional; this class provides default
+                * implementations that do nothing.  In order for seeking to work
+                * you must overide seek_callback(), tell_callback(),
+                * length_callback(), and eof_callback().
                 */
                class FLACPP_API Stream {
                public:
@@ -103,42 +119,74 @@ namespace FLAC {
                        Stream();
                        virtual ~Stream();
 
+                       /** Call after construction to check the that the object was created
+                        *  successfully.  If not, use get_state() to find out why not.
+                        *
+                        * \{
+                        */
                        bool is_valid() const;
                        inline operator bool() const { return is_valid(); }
-
-                       bool set_metadata_respond(::FLAC__MetadataType type);
-                       bool set_metadata_respond_application(const FLAC__byte id[4]);
-                       bool set_metadata_respond_all();
-                       bool set_metadata_ignore(::FLAC__MetadataType type);
-                       bool set_metadata_ignore_application(const FLAC__byte id[4]);
-                       bool set_metadata_ignore_all();
-
-                       State get_state() const;
-                       unsigned get_channels() const;
-                       ::FLAC__ChannelAssignment get_channel_assignment() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
+                       /* \} */
+
+                       bool set_md5_checking(bool value);                             ///< See FLAC__stream_decoder_set_md5_checking()
+                       bool set_metadata_respond(::FLAC__MetadataType type);          ///< See FLAC__stream_decoder_set_metadata_respond()
+                       bool set_metadata_respond_application(const FLAC__byte id[4]); ///< See FLAC__stream_decoder_set_metadata_respond_application()
+                       bool set_metadata_respond_all();                               ///< See FLAC__stream_decoder_set_metadata_respond_all()
+                       bool set_metadata_ignore(::FLAC__MetadataType type);           ///< See FLAC__stream_decoder_set_metadata_ignore()
+                       bool set_metadata_ignore_application(const FLAC__byte id[4]);  ///< See FLAC__stream_decoder_set_metadata_ignore_application()
+                       bool set_metadata_ignore_all();                                ///< See FLAC__stream_decoder_set_metadata_ignore_all()
+
+                       State get_state() const;                                  ///< See FLAC__stream_decoder_get_state()
+                       bool get_md5_checking() const;                            ///< See FLAC__stream_decoder_get_md5_checking()
+                       FLAC__uint64 get_total_samples() const;                   ///< See FLAC__stream_decoder_get_total_samples()
+                       unsigned get_channels() const;                            ///< See FLAC__stream_decoder_get_channels()
+                       ::FLAC__ChannelAssignment get_channel_assignment() const; ///< See FLAC__stream_decoder_get_channel_assignment()
+                       unsigned get_bits_per_sample() const;                     ///< See FLAC__stream_decoder_get_bits_per_sample()
+                       unsigned get_sample_rate() const;                         ///< See FLAC__stream_decoder_get_sample_rate()
+                       unsigned get_blocksize() const;                           ///< See FLAC__stream_decoder_get_blocksize()
 
                        /** Initialize the instance; as with the C interface,
                         *  init() should be called after construction and 'set'
                         *  calls but before any of the 'process' calls.
+                        *
+                        *  See FLAC__stream_decoder_init_stream().
                         */
-                       State init();
+                       ::FLAC__StreamDecoderInitStatus init();
+
+                       void finish(); ///< See FLAC__stream_decoder_finish()
 
-                       void finish();
+                       bool flush(); ///< See FLAC__stream_decoder_flush()
+                       bool reset(); ///< See FLAC__stream_decoder_reset()
 
-                       bool flush();
-                       bool reset();
+                       bool process_single();                ///< See FLAC__stream_decoder_process_single()
+                       bool process_until_end_of_metadata(); ///< See FLAC__stream_decoder_process_until_end_of_metadata()
+                       bool process_until_end_of_stream();   ///< See FLAC__stream_decoder_process_until_end_of_stream()
+                       bool skip_single_frame();             ///< See FLAC__stream_decoder_skip_single_frame()
 
-                       bool process_single();
-                       bool process_until_end_of_metadata();
-                       bool process_until_end_of_stream();
-                       bool skip_single_frame();
+                       bool seek_absolute(FLAC__uint64 sample); ///< See FLAC__stream_decoder_seek_absolute()
                protected:
+                       /// see FLAC__StreamDecoderReadCallback
                        virtual ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0;
+
+                       /// see FLAC__StreamDecoderSeekCallback
+                       virtual ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
+
+                       /// see FLAC__StreamDecoderTellCallback
+                       virtual ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
+
+                       /// see FLAC__StreamDecoderLengthCallback
+                       virtual ::FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length);
+
+                       /// see FLAC__StreamDecoderEofCallback
+                       virtual bool eof_callback();
+
+                       /// see FLAC__StreamDecoderWriteCallback
                        virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0;
-                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0;
+
+                       /// see FLAC__StreamDecoderMetadataCallback
+                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata);
+
+                       /// see FLAC__StreamDecoderErrorCallback
                        virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0;
 
 #if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
@@ -146,12 +194,16 @@ namespace FLAC {
                        friend State;
 #endif
                        ::FLAC__StreamDecoder *decoder_;
-               private:
+
                        static ::FLAC__StreamDecoderReadStatus read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+                       static ::FLAC__StreamDecoderSeekStatus seek_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+                       static ::FLAC__StreamDecoderTellStatus tell_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+                       static ::FLAC__StreamDecoderLengthStatus length_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
+                       static FLAC__bool eof_callback_(const ::FLAC__StreamDecoder *decoder, void *client_data);
                        static ::FLAC__StreamDecoderWriteStatus write_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
                        static void metadata_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
                        static void error_callback_(const ::FLAC__StreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data);
-
+               private:
                        // Private and undefined so you can't use them:
                        Stream(const Stream &);
                        void operator=(const Stream &);
@@ -159,186 +211,56 @@ namespace FLAC {
 
                /* \} */
 
-               // ============================================================
-               //
-               //  Equivalent: FLAC__SeekableStreamDecoder
-               //
-               // ============================================================
-
-               /** \defgroup flacpp_seekable_stream_decoder FLAC++/decoder.h: seekable stream decoder class
+               /** \defgroup flacpp_file_decoder FLAC++/decoder.h: file decoder class
                 *  \ingroup flacpp_decoder
                 *
                 *  \brief
-                *  This class wraps the ::FLAC__SeekableStreamDecoder.
+                *  This class wraps the ::FLAC__StreamDecoder.
                 *
-                * See the \link flac_seekable_stream_decoder libFLAC seekable stream decoder module \endlink.
+                * See the \link flac_stream_decoder libFLAC stream decoder module \endlink
+                * for basic usage.
                 *
                 * \{
                 */
 
-               /** This class wraps the ::FLAC__SeekableStreamDecoder.
-                */
-               class FLACPP_API SeekableStream {
-               public:
-                       class FLACPP_API State {
-                       public:
-                               inline State(::FLAC__SeekableStreamDecoderState state): state_(state) { }
-                               inline operator ::FLAC__SeekableStreamDecoderState() const { return state_; }
-                               inline const char *as_cstring() const { return ::FLAC__SeekableStreamDecoderStateString[state_]; }
-                               inline const char *resolved_as_cstring(const SeekableStream &decoder) const { return ::FLAC__seekable_stream_decoder_get_resolved_state_string(decoder.decoder_); }
-                       protected:
-                               ::FLAC__SeekableStreamDecoderState state_;
-                       };
-
-                       SeekableStream();
-                       virtual ~SeekableStream();
-
-                       bool is_valid() const;
-                       inline operator bool() const { return is_valid(); }
-
-                       bool set_md5_checking(bool value);
-                       bool set_metadata_respond(::FLAC__MetadataType type);
-                       bool set_metadata_respond_application(const FLAC__byte id[4]);
-                       bool set_metadata_respond_all();
-                       bool set_metadata_ignore(::FLAC__MetadataType type);
-                       bool set_metadata_ignore_application(const FLAC__byte id[4]);
-                       bool set_metadata_ignore_all();
-
-                       State get_state() const;
-                       Stream::State get_stream_decoder_state() const;
-                       bool get_md5_checking() const;
-                       unsigned get_channels() const;
-                       ::FLAC__ChannelAssignment get_channel_assignment() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-
-                       State init();
-
-                       bool finish();
-
-                       bool flush();
-                       bool reset();
-
-                       bool process_single();
-                       bool process_until_end_of_metadata();
-                       bool process_until_end_of_stream();
-                       bool skip_single_frame();
-
-                       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 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;
-                       virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0;
-
-#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
-                       // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring()
-                       friend State;
-#endif
-                       ::FLAC__SeekableStreamDecoder *decoder_;
-               private:
-                       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);
-
-                       // Private and undefined so you can't use them:
-                       SeekableStream(const SeekableStream &);
-                       void operator=(const SeekableStream &);
-               };
-
-               /* \} */
-
-               // ============================================================
-               //
-               //  Equivalent: FLAC__FileDecoder
-               //
-               // ============================================================
-
-               /** \defgroup flacpp_file_decoder FLAC++/decoder.h: file decoder class
-                *  \ingroup flacpp_decoder
+               /** This class wraps the ::FLAC__StreamDecoder.  If you are
+                *  not decoding from a file, you may need to use
+                *  FLAC::Decoder::Stream.
                 *
-                *  \brief
-                *  This class wraps the ::FLAC__FileDecoder.
-                *
-                * See the \link flac_file_decoder libFLAC file decoder module \endlink.
+                * The usage of this class is similar to FLAC__StreamDecoder,
+                * except instead of providing callbacks to
+                * FLAC__stream_decoder_init_FILE() or
+                * FLAC__stream_decoder_init_file(), you will inherit from this
+                * class and override the virtual callback functions with your
+                * own implementations, then call File::init().  The rest of
+                * the calls work the same as in the C layer.
                 *
-                * \{
-                */
-
-               /** This class wraps the ::FLAC__FileDecoder.
+                * Only the write, and error callbacks from FLAC::Decoder::Stream
+                * are mandatory.  The others are optional; this class provides
+                * full working implementations for all other callbacks and
+                * supports seeking.
                 */
-               class FLACPP_API File {
+               class FLACPP_API File: public Stream {
                public:
-                       class FLACPP_API State {
-                       public:
-                               inline State(::FLAC__FileDecoderState state): state_(state) { }
-                               inline operator ::FLAC__FileDecoderState() const { return state_; }
-                               inline const char *as_cstring() const { return ::FLAC__FileDecoderStateString[state_]; }
-                               inline const char *resolved_as_cstring(const File &decoder) const { return ::FLAC__file_decoder_get_resolved_state_string(decoder.decoder_); }
-                       protected:
-                               ::FLAC__FileDecoderState state_;
-                       };
-
                        File();
                        virtual ~File();
 
-                       bool is_valid() const;
-                       inline operator bool() const { return is_valid(); }
-
-                       bool set_md5_checking(bool value);
-                       bool set_filename(const char *value); //!< 'value' may not be \c NULL; use "-" for stdin
-                       bool set_metadata_respond(::FLAC__MetadataType type);
-                       bool set_metadata_respond_application(const FLAC__byte id[4]);
-                       bool set_metadata_respond_all();
-                       bool set_metadata_ignore(::FLAC__MetadataType type);
-                       bool set_metadata_ignore_application(const FLAC__byte id[4]);
-                       bool set_metadata_ignore_all();
-
-                       State get_state() const;
-                       SeekableStream::State get_seekable_stream_decoder_state() const;
-                       Stream::State get_stream_decoder_state() const;
-                       bool get_md5_checking() const;
-                       unsigned get_channels() const;
-                       ::FLAC__ChannelAssignment get_channel_assignment() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-
-                       State init();
-
-                       bool finish();
-
-                       bool process_single();
-                       bool process_until_end_of_metadata();
-                       bool process_until_end_of_file();
-                       bool skip_single_frame();
-
-                       bool seek_absolute(FLAC__uint64 sample);
+                       /** Initialize the instance; as with the C interface,
+                        *  init() should be called after construction and 'set'
+                        *  calls but before any of the 'process' calls.
+                        *
+                        *  See FLAC__stream_decoder_init_FILE() and
+                        *  FLAC__stream_decoder_init_file().
+                        *  \{
+                        */
+                       ::FLAC__StreamDecoderInitStatus init(FILE *file);
+                       ::FLAC__StreamDecoderInitStatus init(const char *filename);
+                       ::FLAC__StreamDecoderInitStatus init(const std::string &filename);
+                       /*  \} */
                protected:
-                       virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0;
-                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0;
-                       virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0;
-
-#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
-                       // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring()
-                       friend State;
-#endif
-                       ::FLAC__FileDecoder *decoder_;
+                       // this is a dummy implementation to satisfy the pure virtual in Stream that is actually supplied internally by the C layer
+                       virtual ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
                private:
-                       static ::FLAC__StreamDecoderWriteStatus write_callback_(const ::FLAC__FileDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-                       static void metadata_callback_(const ::FLAC__FileDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
-                       static void error_callback_(const ::FLAC__FileDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data);
-
                        // Private and undefined so you can't use them:
                        File(const File &);
                        void operator=(const File &);
index 88768ae..4e31011 100644 (file)
@@ -34,8 +34,6 @@
 
 #include "export.h"
 
-#include "FLAC/file_encoder.h"
-#include "FLAC/seekable_stream_encoder.h"
 #include "FLAC/stream_encoder.h"
 #include "decoder.h"
 #include "metadata.h"
  *  \ingroup flacpp
  *
  *  \brief
- *  This module describes the three encoder layers provided by libFLAC++.
+ *  This module describes the encoder layers provided by libFLAC++.
  *
  * The libFLAC++ encoder classes are object wrappers around their
- * counterparts in libFLAC.  All three encoding layers available in
+ * counterparts in libFLAC.  All decoding layers available in
  * libFLAC are also provided here.  The interface is very similar;
  * make sure to read the \link flac_encoder libFLAC encoder module \endlink.
  *
- * The only real difference here is that instead of passing in C function
- * pointers for callbacks, you inherit from the encoder class and provide
- * implementations for the callbacks in the derived class; because of this
- * there is no need for a 'client_data' property.
+ * There are only two significant differences here.  First, instead of
+ * passing in C function pointers for callbacks, you inherit from the
+ * encoder class and provide implementations for the callbacks in your
+ * derived class; because of this there is no need for a 'client_data'
+ * property.
+ *
+ * Second, there are two stream encoder classes.  FLAC::Encoder::Stream
+ * is used for the same cases that FLAC__stream_encoder_init_stream() is
+ * used, and FLAC::Encoder::File is used for the same cases that
+ * FLAC__stream_encoder_init_FILE() and FLAC__stream_encoder_init_file()
+ * are used.
  */
 
 namespace FLAC {
        namespace Encoder {
 
-               // ============================================================
-               //
-               //  Equivalent: FLAC__StreamEncoder
-               //
-               // ============================================================
-
                /** \defgroup flacpp_stream_encoder FLAC++/encoder.h: stream encoder class
                 *  \ingroup flacpp_encoder
                 *
                 *  \brief
                 *  This class wraps the ::FLAC__StreamEncoder.
                 *
-                * See the \link flac_stream_encoder libFLAC stream encoder module \endlink.
+                * See the \link flac_stream_encoder libFLAC stream encoder module \endlink
+                * for basic usage.
                 *
                 * \{
                 */
 
-               /** This class wraps the ::FLAC__StreamEncoder.
+               /** This class wraps the ::FLAC__StreamEncoder.  If you are
+                *  encoding to a file, FLAC::Encoder::File may be more
+                *  convenient.
+                *
+                * The usage of this class is similar to FLAC__StreamEncoder,
+                * except instead of providing callbacks to
+                * FLAC__stream_encoder_init_stream(), you will inherit from this
+                * class and override the virtual callback functions with your
+                * own implementations, then call Stream::init().  The rest of
+                * the calls work the same as in the C layer.
+                *
+                * Only the write callback is mandatory.  The others are
+                * optional; this class provides default implementations that do
+                * nothing.  In order for some STREAMINFO and SEEKTABLE data to
+                * be written properly, you must overide seek_callback() and
+                * tell_callback(); see FLAC__stream_encoder_init_stream() as to
+                * why.
                 */
                class FLACPP_API Stream {
                public:
@@ -105,70 +121,93 @@ namespace FLAC {
                        Stream();
                        virtual ~Stream();
 
+                       /** Call after construction to check the that the object was created
+                        *  successfully.  If not, use get_state() to find out why not.
+                        *
+                        * \{
+                        */
                        bool is_valid() const;
                        inline operator bool() const { return is_valid(); }
+                       /* \} */
+
+                       bool set_verify(bool value);                            ///< See FLAC__stream_encoder_set_verify()
+                       bool set_streamable_subset(bool value);                 ///< See FLAC__stream_encoder_set_streamable_subset()
+                       bool set_do_mid_side_stereo(bool value);                ///< See FLAC__stream_encoder_set_do_mid_side_stereo()
+                       bool set_loose_mid_side_stereo(bool value);             ///< See FLAC__stream_encoder_set_loose_mid_side_stereo()
+                       bool set_channels(unsigned value);                      ///< See FLAC__stream_encoder_set_channels()
+                       bool set_bits_per_sample(unsigned value);               ///< See FLAC__stream_encoder_set_bits_per_sample()
+                       bool set_sample_rate(unsigned value);                   ///< See FLAC__stream_encoder_set_sample_rate()
+                       bool set_blocksize(unsigned value);                     ///< See FLAC__stream_encoder_set_blocksize()
+                       bool set_apodization(const char *specification);        ///< See FLAC__stream_encoder_set_apodization()
+                       bool set_max_lpc_order(unsigned value);                 ///< See FLAC__stream_encoder_set_max_lpc_order()
+                       bool set_qlp_coeff_precision(unsigned value);           ///< See FLAC__stream_encoder_set_qlp_coeff_precision()
+                       bool set_do_qlp_coeff_prec_search(bool value);          ///< See FLAC__stream_encoder_set_do_qlp_coeff_prec_search()
+                       bool set_do_escape_coding(bool value);                  ///< See FLAC__stream_encoder_set_do_escape_coding()
+                       bool set_do_exhaustive_model_search(bool value);        ///< See FLAC__stream_encoder_set_do_exhaustive_model_search()
+                       bool set_min_residual_partition_order(unsigned value);  ///< See FLAC__stream_encoder_set_min_residual_partition_order()
+                       bool set_max_residual_partition_order(unsigned value);  ///< See FLAC__stream_encoder_set_max_residual_partition_order()
+                       bool set_rice_parameter_search_dist(unsigned value);    ///< See FLAC__stream_encoder_set_rice_parameter_search_dist()
+                       bool set_total_samples_estimate(FLAC__uint64 value);    ///< See FLAC__stream_encoder_set_total_samples_estimate()
+                       bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks);    ///< See FLAC__stream_encoder_set_metadata()
+                       bool set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks); ///< See FLAC__stream_encoder_set_metadata()
+
+                       State    get_state() const;                              ///< See FLAC__stream_encoder_get_state()
+                       Decoder::Stream::State get_verify_decoder_state() const; ///< See FLAC__stream_encoder_get_verify_decoder_state()
+                       void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got); ///< See FLAC__stream_encoder_get_verify_decoder_error_stats()
+                       bool     get_verify() const;                       ///< See FLAC__stream_encoder_get_verify()
+                       bool     get_streamable_subset() const;            ///< See FLAC__stream_encoder_get_streamable_subset()
+                       bool     get_do_mid_side_stereo() const;           ///< See FLAC__stream_encoder_get_do_mid_side_stereo()
+                       bool     get_loose_mid_side_stereo() const;        ///< See FLAC__stream_encoder_get_loose_mid_side_stereo()
+                       unsigned get_channels() const;                     ///< See FLAC__stream_encoder_get_channels()
+                       unsigned get_bits_per_sample() const;              ///< See FLAC__stream_encoder_get_bits_per_sample()
+                       unsigned get_sample_rate() const;                  ///< See FLAC__stream_encoder_get_sample_rate()
+                       unsigned get_blocksize() const;                    ///< See FLAC__stream_encoder_get_blocksize()
+                       unsigned get_max_lpc_order() const;                ///< See FLAC__stream_encoder_get_max_lpc_order()
+                       unsigned get_qlp_coeff_precision() const;          ///< See FLAC__stream_encoder_get_qlp_coeff_precision()
+                       bool     get_do_qlp_coeff_prec_search() const;     ///< See FLAC__stream_encoder_get_do_qlp_coeff_prec_search()
+                       bool     get_do_escape_coding() const;             ///< See FLAC__stream_encoder_get_do_escape_coding()
+                       bool     get_do_exhaustive_model_search() const;   ///< See FLAC__stream_encoder_get_do_exhaustive_model_search()
+                       unsigned get_min_residual_partition_order() const; ///< See FLAC__stream_encoder_get_min_residual_partition_order()
+                       unsigned get_max_residual_partition_order() const; ///< See FLAC__stream_encoder_get_max_residual_partition_order()
+                       unsigned get_rice_parameter_search_dist() const;   ///< See FLAC__stream_encoder_get_rice_parameter_search_dist()
+                       FLAC__uint64 get_total_samples_estimate() const;   ///< See FLAC__stream_encoder_get_total_samples_estimate()
+
+                       /** Initialize the instance; as with the C interface,
+                        *  init() should be called after construction and 'set'
+                        *  calls but before any of the 'process' calls.
+                        *
+                        *  See FLAC__stream_encoder_init_stream().
+                        */
+                       ::FLAC__StreamEncoderInitStatus init();
+
+                       void finish(); ///< See FLAC__stream_encoder_finish()
+
+                       bool process(const FLAC__int32 * const buffer[], unsigned samples);     ///< See FLAC__stream_encoder_process()
+                       bool process_interleaved(const FLAC__int32 buffer[], unsigned samples); ///< See FLAC__stream_encoder_process_interleaved()
+               protected:
+                       /// See FLAC__StreamEncoderWriteCallback
+                       virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame) = 0;
 
-                       bool set_verify(bool value);
-                       bool set_streamable_subset(bool value);
-                       bool set_do_mid_side_stereo(bool value);
-                       bool set_loose_mid_side_stereo(bool value);
-                       bool set_channels(unsigned value);
-                       bool set_bits_per_sample(unsigned value);
-                       bool set_sample_rate(unsigned value);
-                       bool set_blocksize(unsigned value);
-                       bool set_apodization(const char *specification);
-                       bool set_max_lpc_order(unsigned value);
-                       bool set_qlp_coeff_precision(unsigned value);
-                       bool set_do_qlp_coeff_prec_search(bool value);
-                       bool set_do_escape_coding(bool value);
-                       bool set_do_exhaustive_model_search(bool value);
-                       bool set_min_residual_partition_order(unsigned value);
-                       bool set_max_residual_partition_order(unsigned value);
-                       bool set_rice_parameter_search_dist(unsigned value);
-                       bool set_total_samples_estimate(FLAC__uint64 value);
-                       bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks);
-                       bool set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks);
-
-                       State    get_state() const;
-                       Decoder::Stream::State get_verify_decoder_state() const;
-                       void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-                       bool     get_verify() const;
-                       bool     get_streamable_subset() const;
-                       bool     get_do_mid_side_stereo() const;
-                       bool     get_loose_mid_side_stereo() const;
-                       unsigned get_channels() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-                       unsigned get_max_lpc_order() const;
-                       unsigned get_qlp_coeff_precision() const;
-                       bool     get_do_qlp_coeff_prec_search() const;
-                       bool     get_do_escape_coding() const;
-                       bool     get_do_exhaustive_model_search() const;
-                       unsigned get_min_residual_partition_order() const;
-                       unsigned get_max_residual_partition_order() const;
-                       unsigned get_rice_parameter_search_dist() const;
-                       FLAC__uint64 get_total_samples_estimate() const;
+                       /// See FLAC__StreamEncoderSeekCallback
+                       virtual ::FLAC__StreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
 
-                       State init();
+                       /// See FLAC__StreamEncoderTellCallback
+                       virtual ::FLAC__StreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
 
-                       void finish();
-
-                       bool process(const FLAC__int32 * const buffer[], unsigned samples);
-                       bool process_interleaved(const FLAC__int32 buffer[], unsigned samples);
-               protected:
-                       virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame) = 0;
-                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0;
+                       /// See FLAC__StreamEncoderTellCallback
+                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata);
 
 #if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
                        // lame hack: some MSVC/GCC versions can't see a protected encoder_ from nested State::resolved_as_cstring()
                        friend State;
 #endif
                        ::FLAC__StreamEncoder *encoder_;
-               private:
+
                        static ::FLAC__StreamEncoderWriteStatus write_callback_(const ::FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
+                       static ::FLAC__StreamEncoderSeekStatus seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+                       static ::FLAC__StreamEncoderTellStatus tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
                        static void metadata_callback_(const ::FLAC__StreamEncoder *encoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
-
+               private:
                        // Private and undefined so you can't use them:
                        Stream(const Stream &);
                        void operator=(const Stream &);
@@ -176,200 +215,61 @@ namespace FLAC {
 
                /* \} */
 
-               /** \defgroup flacpp_seekable_stream_encoder FLAC++/encoder.h: seekable stream encoder class
+               /** \defgroup flacpp_file_encoder FLAC++/encoder.h: file encoder class
                 *  \ingroup flacpp_encoder
                 *
                 *  \brief
-                *  This class wraps the ::FLAC__SeekableStreamEncoder.
+                *  This class wraps the ::FLAC__StreamEncoder.
                 *
-                * See the \link flac_seekable_stream_encoder libFLAC seekable stream encoder module \endlink.
+                * See the \link flac_stream_encoder libFLAC stream encoder module \endlink
+                * for basic usage.
                 *
                 * \{
                 */
 
-               /** This class wraps the ::FLAC__SeekableStreamEncoder.
-                */
-               class FLACPP_API SeekableStream {
-               public:
-                       class FLACPP_API State {
-                       public:
-                               inline State(::FLAC__SeekableStreamEncoderState state): state_(state) { }
-                               inline operator ::FLAC__SeekableStreamEncoderState() const { return state_; }
-                               inline const char *as_cstring() const { return ::FLAC__SeekableStreamEncoderStateString[state_]; }
-                               inline const char *resolved_as_cstring(const SeekableStream &encoder) const { return ::FLAC__seekable_stream_encoder_get_resolved_state_string(encoder.encoder_); }
-                       protected:
-                               ::FLAC__SeekableStreamEncoderState state_;
-                       };
-
-                       SeekableStream();
-                       virtual ~SeekableStream();
-
-                       bool is_valid() const;
-                       inline operator bool() const { return is_valid(); }
-
-                       bool set_verify(bool value);
-                       bool set_streamable_subset(bool value);
-                       bool set_do_mid_side_stereo(bool value);
-                       bool set_loose_mid_side_stereo(bool value);
-                       bool set_channels(unsigned value);
-                       bool set_bits_per_sample(unsigned value);
-                       bool set_sample_rate(unsigned value);
-                       bool set_blocksize(unsigned value);
-                       bool set_apodization(const char *specification);
-                       bool set_max_lpc_order(unsigned value);
-                       bool set_qlp_coeff_precision(unsigned value);
-                       bool set_do_qlp_coeff_prec_search(bool value);
-                       bool set_do_escape_coding(bool value);
-                       bool set_do_exhaustive_model_search(bool value);
-                       bool set_min_residual_partition_order(unsigned value);
-                       bool set_max_residual_partition_order(unsigned value);
-                       bool set_rice_parameter_search_dist(unsigned value);
-                       bool set_total_samples_estimate(FLAC__uint64 value);
-                       bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks);
-                       bool set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks);
-
-                       State    get_state() const;
-                       Stream::State get_stream_encoder_state() const;
-                       Decoder::Stream::State get_verify_decoder_state() const;
-                       void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-                       bool     get_verify() const;
-                       bool     get_streamable_subset() const;
-                       bool     get_do_mid_side_stereo() const;
-                       bool     get_loose_mid_side_stereo() const;
-                       unsigned get_channels() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-                       unsigned get_max_lpc_order() const;
-                       unsigned get_qlp_coeff_precision() const;
-                       bool     get_do_qlp_coeff_prec_search() const;
-                       bool     get_do_escape_coding() const;
-                       bool     get_do_exhaustive_model_search() const;
-                       unsigned get_min_residual_partition_order() const;
-                       unsigned get_max_residual_partition_order() const;
-                       unsigned get_rice_parameter_search_dist() const;
-                       FLAC__uint64 get_total_samples_estimate() const;
-
-                       State init();
-
-                       void finish();
-
-                       bool process(const FLAC__int32 * const buffer[], unsigned samples);
-                       bool process_interleaved(const FLAC__int32 buffer[], unsigned samples);
-               protected:
-                       virtual ::FLAC__SeekableStreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) = 0;
-                       virtual ::FLAC__SeekableStreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) = 0;
-                       virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame) = 0;
-
-#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
-                       // lame hack: some MSVC/GCC versions can't see a protected encoder_ from nested State::resolved_as_cstring()
-                       friend State;
-#endif
-                       ::FLAC__SeekableStreamEncoder *encoder_;
-               private:
-                       static ::FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-                       static ::FLAC__SeekableStreamEncoderTellStatus tell_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-                       static ::FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-
-                       // Private and undefined so you can't use them:
-                       SeekableStream(const SeekableStream &);
-                       void operator=(const SeekableStream &);
-               };
-
-               /* \} */
-
-               /** \defgroup flacpp_file_encoder FLAC++/encoder.h: file encoder class
-                *  \ingroup flacpp_encoder
+               /** This class wraps the ::FLAC__StreamEncoder.  If you are
+                *  not encoding to a file, you may need to use
+                *  FLAC::Encoder::Stream.
                 *
-                *  \brief
-                *  This class wraps the ::FLAC__FileEncoder.
-                *
-                * See the \link flac_file_encoder libFLAC file encoder module \endlink.
+                * The usage of this class is similar to FLAC__StreamEncoder,
+                * except instead of providing callbacks to
+                * FLAC__stream_encoder_init_FILE() or
+                * FLAC__stream_encoder_init_file(), you will inherit from this
+                * class and override the virtual callback functions with your
+                * own implementations, then call File::init().  The rest of
+                * the calls work the same as in the C layer.
                 *
-                * \{
-                */
-
-               /** This class wraps the ::FLAC__FileEncoder.
+                * There are no mandatory callbacks; all the callbacks from
+                * FLAC::Encoder::Stream are implemented here fully and support
+                * full post-encode STREAMINFO and SEEKTABLE updating.  There is
+                * only an optional progress callback which you may override to
+                * get periodic reports on the progress of the encode.
                 */
-               class FLACPP_API File {
+               class FLACPP_API File: public Stream {
                public:
-                       class FLACPP_API State {
-                       public:
-                               inline State(::FLAC__FileEncoderState state): state_(state) { }
-                               inline operator ::FLAC__FileEncoderState() const { return state_; }
-                               inline const char *as_cstring() const { return ::FLAC__FileEncoderStateString[state_]; }
-                               inline const char *resolved_as_cstring(const File &encoder) const { return ::FLAC__file_encoder_get_resolved_state_string(encoder.encoder_); }
-                       protected:
-                               ::FLAC__FileEncoderState state_;
-                       };
-
+                       /** Initialize the instance; as with the C interface,
+                        *  init() should be called after construction and 'set'
+                        *  calls but before any of the 'process' calls.
+                        *
+                        *  See FLAC__stream_encoder_init_FILE() and
+                        *  FLAC__stream_encoder_init_file().
+                        *  \{
+                        */
                        File();
                        virtual ~File();
+                       /*  \} */
 
-                       bool is_valid() const;
-                       inline operator bool() const { return is_valid(); }
-
-                       bool set_verify(bool value);
-                       bool set_streamable_subset(bool value);
-                       bool set_do_mid_side_stereo(bool value);
-                       bool set_loose_mid_side_stereo(bool value);
-                       bool set_channels(unsigned value);
-                       bool set_bits_per_sample(unsigned value);
-                       bool set_sample_rate(unsigned value);
-                       bool set_blocksize(unsigned value);
-                       bool set_apodization(const char *specification);
-                       bool set_max_lpc_order(unsigned value);
-                       bool set_qlp_coeff_precision(unsigned value);
-                       bool set_do_qlp_coeff_prec_search(bool value);
-                       bool set_do_escape_coding(bool value);
-                       bool set_do_exhaustive_model_search(bool value);
-                       bool set_min_residual_partition_order(unsigned value);
-                       bool set_max_residual_partition_order(unsigned value);
-                       bool set_rice_parameter_search_dist(unsigned value);
-                       bool set_total_samples_estimate(FLAC__uint64 value);
-                       bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks);
-                       bool set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks);
-                       bool set_filename(const char *value);
-
-                       State    get_state() const;
-                       SeekableStream::State get_seekable_stream_encoder_state() const;
-                       Stream::State get_stream_encoder_state() const;
-                       Decoder::Stream::State get_verify_decoder_state() const;
-                       void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-                       bool     get_verify() const;
-                       bool     get_streamable_subset() const;
-                       bool     get_do_mid_side_stereo() const;
-                       bool     get_loose_mid_side_stereo() const;
-                       unsigned get_channels() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-                       unsigned get_max_lpc_order() const;
-                       unsigned get_qlp_coeff_precision() const;
-                       bool     get_do_qlp_coeff_prec_search() const;
-                       bool     get_do_escape_coding() const;
-                       bool     get_do_exhaustive_model_search() const;
-                       unsigned get_min_residual_partition_order() const;
-                       unsigned get_max_residual_partition_order() const;
-                       unsigned get_rice_parameter_search_dist() const;
-                       FLAC__uint64 get_total_samples_estimate() const;
-
-                       State init();
-
-                       void finish();
-
-                       bool process(const FLAC__int32 * const buffer[], unsigned samples);
-                       bool process_interleaved(const FLAC__int32 buffer[], unsigned samples);
+                       ::FLAC__StreamEncoderInitStatus init(FILE *file);
+                       ::FLAC__StreamEncoderInitStatus init(const char *filename);
+                       ::FLAC__StreamEncoderInitStatus init(const std::string &filename);
                protected:
+                       /// See FLAC__StreamEncoderProgressCallback
                        virtual void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate);
 
-#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
-                       // lame hack: some MSVC/GCC versions can't see a protected encoder_ from nested State::resolved_as_cstring()
-                       friend State;
-#endif
-                       ::FLAC__FileEncoder *encoder_;
+                       /// This is a dummy implementation to satisfy the pure virtual in Stream that is actually supplied internally by the C layer
+                       virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame);
                private:
-                       static void progress_callback_(const ::FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
+                       static void progress_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
 
                        // Private and undefined so you can't use them:
                        File(const Stream &);
index 6d93500..a7a1681 100644 (file)
@@ -35,12 +35,8 @@ flaccinclude_HEADERS = \
        assert.h \
        callback.h \
        export.h \
-       file_decoder.h \
-       file_encoder.h \
        format.h \
        metadata.h \
        ordinals.h \
-       seekable_stream_decoder.h \
-       seekable_stream_encoder.h \
        stream_decoder.h \
        stream_encoder.h
index 918cabe..e022d11 100644 (file)
 
 #include "assert.h"
 #include "callback.h"
-#include "file_decoder.h"
-#include "file_encoder.h"
 #include "format.h"
 #include "metadata.h"
 #include "ordinals.h"
-#include "seekable_stream_decoder.h"
-#include "seekable_stream_encoder.h"
 #include "stream_decoder.h"
 #include "stream_encoder.h"
 
  * individual functions.  You can see different views of the individual
  * functions through the links in top bar across this page.
  *
+ * \section porting_guide Porting Guide
+ *
+ * Starting with FLAC 1.1.3 a \link porting Porting Guide \endlink
+ * has been introduced which gives detailed instructions on how to
+ * port your code to newer versions of FLAC.
+ *
  * \section embedded_developers Embedded Developers
  *
  * libFLAC has grown larger over time as more functionality has been
  * will greatly reduce the size of the library.
  */
 
+/** \defgroup porting Porting Guide for New Versions
+ *
+ * This module describes differences in the library interfaces from
+ * version to version.  It assists in the porting of code that uses
+ * the libraries to newer versions of FLAC.
+ */
+
+/** \defgroup porting_1_1_2_to_1_1_3 Porting from FLAC 1.1.2 to 1.1.3
+ *  \ingroup porting
+ *
+ *  \brief
+ *  This module describes porting from FLAC 1.1.2 to FLAC 1.1.3.
+ *
+ * The main change between the APIs in 1.1.2 and 1.1.3 is that the three
+ * decoding layers and three encoding layers have been merged into a
+ * single stream decoder and stream encoder.  That is, the functionality
+ * of FLAC__SeekableStreamDecoder and FLAC__FileDecoder has been merged
+ * into FLAC__StreamDecoder, and FLAC__SeekableStreamEncoder and
+ * FLAC__FileEncoder into FLAC__StreamEncoder.  Only the
+ * FLAC__StreamDecoder and FLAC__StreamEncoder remain.  This can
+ * simplify code that needs to process both seekable and non-seekable
+ * streams.
+ *
+ * Instead of creating an encoder or decoder of a certain layer, now the
+ * client will always create a FLAC__StreamEncoder or
+ * FLAC__StreamDecoder.  The different layers are differentiated by the
+ * initialization function.  For example, for the decoder,
+ * FLAC__stream_decoder_init() has been replaced by
+ * FLAC__stream_decoder_init_stream().  This init function takes
+ * callbacks for the I/O, and the seeking callbacks are optional.  This
+ * allows the client to use the same object for seekable and
+ * non-seekable streams.  For decoding a FLAC file directly, the client
+ * can use FLAC__stream_decoder_init_file() and pass just a filename
+ * and fewer callbacks; most of the other callbacks are supplied
+ * internally.  For situations where fopen()ing by filename is not
+ * possible (e.g. Unicode filenames on Windows) the client can instead
+ * open the file itself and supply the FILE* to
+ * FLAC__stream_decoder_init_FILE().  The init functions now returns a
+ * FLAC__StreamDecoderInitStatus instead of FLAC__StreamDecoderState.
+ * Since the callbacks and client data are now passed to the init
+ * function, the FLAC__stream_decoder_set_*_callback() functions and
+ * FLAC__stream_decoder_set_client_data() are no longer needed.  The
+ * rest of the calls to the decoder are the same as before.
+ *
+ * As an example, in FLAC 1.1.2 a seekable stream decoder would be set
+ * up like so:
+ *@@@@@@CHECK@@@@@@
+ * \code
+ * FLAC__SeekableStreamDecoder *decoder = FLAC__seekable_stream_decoder_new();
+ * if(decoder == NULL) do something;
+ * FLAC__seekable_stream_decoder_set_md5_checking(decoder, true);
+ * [... other settings ...]
+ * FLAC__seekable_stream_decoder_set_read_callback(decoder, my_read_callback);
+ * FLAC__seekable_stream_decoder_set_seek_callback(decoder, my_seek_callback);
+ * FLAC__seekable_stream_decoder_set_tell_callback(decoder, my_tell_callback);
+ * FLAC__seekable_stream_decoder_set_length_callback(decoder, my_length_callback);
+ * FLAC__seekable_stream_decoder_set_eof_callback(decoder, my_eof_callback);
+ * FLAC__seekable_stream_decoder_set_write_callback(decoder, my_write_callback);
+ * FLAC__seekable_stream_decoder_set_metadata_callback(decoder, my_metadata_callback);
+ * FLAC__seekable_stream_decoder_set_error_callback(decoder, my_error_callback);
+ * FLAC__seekable_stream_decoder_set_client_data(decoder, my_client_data);
+ * if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) do something;
+ * \endcode
+ *
+ * In FLAC 1.1.3 it is like this:
+ *
+ * \code
+ * FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new();
+ * if(decoder == NULL) do something;
+ * FLAC__stream_decoder_set_md5_checking(decoder, true);
+ * [... other settings ...]
+ * if(FLAC__stream_decoder_init_stream(
+ *   decoder,
+ *   my_read_callback,
+ *   my_seek_callback,      // or NULL
+ *   my_tell_callback,      // or NULL
+ *   my_length_callback,    // or NULL
+ *   my_eof_callback,       // or NULL
+ *   my_write_callback,
+ *   my_metadata_callback,  // or NULL
+ *   my_error_callback,
+ *   my_client_data,
+ * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do something;
+ * \endcode
+ *
+ * or you could do;
+ *
+ * \code
+ * [...]
+ * FILE *file = fopen("somefile.flac","rb");
+ * if(file == NULL) do somthing;
+ * if(FLAC__stream_decoder_init_FILE(
+ *   decoder,
+ *   file,
+ *   my_write_callback,
+ *   my_metadata_callback,  // or NULL
+ *   my_error_callback,
+ *   my_client_data,
+ * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do something;
+ * \endcode
+ *
+ * or just:
+ *
+ * \code
+ * [...]
+ * if(FLAC__stream_decoder_init_FILE(
+ *   decoder,
+ *   "somefile.flac",
+ *   my_write_callback,
+ *   my_metadata_callback,  // or NULL
+ *   my_error_callback,
+ *   my_client_data,
+ * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do something;
+ * \endcode
+ *
+ * Another small change to the decoder is in how it handles unparseable
+ * streams.  Before, when the decoder found an unparseable stream
+ * (reserved for when the decoder encounters a stream from a future
+ * encoder that it can't parse), it changed the state to
+ * \c FLAC__STREAM_DECODER_UNPARSEABLE_STREAM.  Now the decoder instead
+ * drops sync and calls the error callback with a new error code
+ * \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM.  This is
+ * more robust.  If your error callback does not discriminate on the the
+ * error state, your code does not need to be changed.
+ *
+ * The encoder now has a new setting:
+ * FLAC__stream_encoder_set_apodization().  This is for setting the
+ * method used to window the data before LPC analysis.  You only need to
+ * add a call to this function if the default is not   There are also
+ * two new convenience functions that may be useful:
+ * FLAC__metadata_object_cuesheet_calculate_cddb_id() and
+ * FLAC__metadata_get_cuesheet().
+ */
+
 /** \defgroup flac FLAC C API
  *
  * The FLAC C API is the interface to libFLAC, a set of structures
diff --git a/include/FLAC/file_decoder.h b/include/FLAC/file_decoder.h
deleted file mode 100644 (file)
index 9c83b0d..0000000
+++ /dev/null
@@ -1,660 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006 Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLAC__FILE_DECODER_H
-#define FLAC__FILE_DECODER_H
-
-#include "export.h"
-#include "seekable_stream_decoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** \file include/FLAC/file_decoder.h
- *
- *  \brief
- *  This module contains the functions which implement the file
- *  decoder.
- *
- *  See the detailed documentation in the
- *  \link flac_file_decoder file decoder \endlink module.
- */
-
-/** \defgroup flac_file_decoder FLAC/file_decoder.h: file decoder interface
- *  \ingroup flac_decoder
- *
- *  \brief
- *  This module contains the functions which implement the file
- *  decoder.
- *
- * The basic usage of this decoder is as follows:
- * - The program creates an instance of a decoder using
- *   FLAC__file_decoder_new().
- * - The program overrides the default settings and sets callbacks for
- *   writing, error reporting, and metadata reporting using
- *   FLAC__file_decoder_set_*() functions.
- * - The program initializes the instance to validate the settings and
- *   prepare for decoding using FLAC__file_decoder_init().
- * - The program calls the FLAC__file_decoder_process_*() functions
- *   to decode data, which subsequently calls the callbacks.
- * - The program finishes the decoding with FLAC__file_decoder_finish(),
- *   which flushes the input and output and resets the decoder to the
- *   uninitialized state.
- * - The instance may be used again or deleted with
- *   FLAC__file_decoder_delete().
- *
- * The file decoder is a trivial wrapper around the
- * \link flac_seekable_stream_decoder seekable stream decoder \endlink
- * meant to simplfy the process of decoding from a standard file.  The
- * file decoder supplies all but the Write/Metadata/Error callbacks.
- * The user needs only to provide the path to the file and the file
- * decoder handles the rest.
- *
- * Like the seekable stream decoder, seeking is exposed through the
- * FLAC__file_decoder_seek_absolute() method.  At any point after the file
- * decoder has been initialized, the user can call this function to seek to
- * an exact sample within the file.  Subsequently, the first time the write
- * callback is called it will be passed a (possibly partial) block starting
- * at that sample.
- *
- * The file decoder also inherits MD5 signature checking from the seekable
- * stream decoder.  If this is turned on before initialization,
- * FLAC__file_decoder_finish() will report when the decoded MD5 signature
- * does not match the one stored in the STREAMINFO block.  MD5 checking is
- * automatically turned off if there is no signature in the STREAMINFO
- * block or when a seek is attempted.
- *
- * Make sure to read the detailed descriptions of the
- * \link flac_seekable_stream_decoder seekable stream decoder module \endlink
- * and \link flac_stream_decoder stream decoder module \endlink
- * since the file decoder inherits much of its behavior from them.
- *
- * \note
- * The "set" functions may only be called when the decoder is in the
- * state FLAC__FILE_DECODER_UNINITIALIZED, i.e. after
- * FLAC__file_decoder_new() or FLAC__file_decoder_finish(), but
- * before FLAC__file_decoder_init().  If this is the case they will
- * return \c true, otherwise \c false.
- *
- * \note
- * FLAC__file_decoder_finish() resets all settings to the constructor
- * defaults, including the callbacks.
- *
- * \{
- */
-
-
-/** State values for a FLAC__FileDecoder
- *
- *  The decoder's state can be obtained by calling FLAC__file_decoder_get_state().
- */
-typedef enum {
-
-       FLAC__FILE_DECODER_OK = 0,
-       /**< The decoder is in the normal OK state. */
-
-       FLAC__FILE_DECODER_END_OF_FILE,
-       /**< The decoder has reached the end of the file. */
-
-       FLAC__FILE_DECODER_ERROR_OPENING_FILE,
-       /**< An error occurred opening the input file. */
-
-       FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR,
-       /**< An error occurred allocating memory. */
-
-       FLAC__FILE_DECODER_SEEK_ERROR,
-       /**< An error occurred while seeking. */
-
-       FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR,
-       /**< An error occurred in the underlying seekable stream decoder. */
-
-       FLAC__FILE_DECODER_ALREADY_INITIALIZED,
-       /**< FLAC__file_decoder_init() was called when the decoder was already
-        * initialized, usually because FLAC__file_decoder_finish() was not
-        * called.
-        */
-
-       FLAC__FILE_DECODER_INVALID_CALLBACK,
-       /**< FLAC__file_decoder_init() was called without all callbacks
-        * being set.
-        */
-
-       FLAC__FILE_DECODER_UNINITIALIZED
-       /**< The decoder is in the uninitialized state. */
-
-} FLAC__FileDecoderState;
-
-/** Maps a FLAC__FileDecoderState to a C string.
- *
- *  Using a FLAC__FileDecoderState as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__FileDecoderStateString[];
-
-
-/***********************************************************************
- *
- * class FLAC__FileDecoder : public FLAC__StreamDecoder
- *
- ***********************************************************************/
-
-struct FLAC__FileDecoderProtected;
-struct FLAC__FileDecoderPrivate;
-/** The opaque structure definition for the file decoder type.  See the
- *  \link flac_file_decoder file decoder module \endlink for a detailed
- *  description.
- */
-typedef struct {
-       struct FLAC__FileDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */
-       struct FLAC__FileDecoderPrivate *private_; /* avoid the C++ keyword 'private' */
-} FLAC__FileDecoder;
-
-/** Signature for the write callback.
- *  See FLAC__file_decoder_set_write_callback()
- *  and FLAC__SeekableStreamDecoderWriteCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  frame    The description of the decoded frame.
- * \param  buffer   An array of pointers to decoded channels of data.
- * \param  client_data  The callee's client data set through
- *                      FLAC__file_decoder_set_client_data().
- * \retval FLAC__StreamDecoderWriteStatus
- *    The callee's return status.
- */
-typedef FLAC__StreamDecoderWriteStatus (*FLAC__FileDecoderWriteCallback)(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-
-/** Signature for the metadata callback.
- *  See FLAC__file_decoder_set_metadata_callback()
- *  and FLAC__SeekableStreamDecoderMetadataCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  metadata The decoded metadata block.
- * \param  client_data  The callee's client data set through
- *                      FLAC__file_decoder_set_client_data().
- */
-typedef void (*FLAC__FileDecoderMetadataCallback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-
-/** Signature for the error callback.
- *  See FLAC__file_decoder_set_error_callback()
- *  and FLAC__SeekableStreamDecoderErrorCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  status   The error encountered by the decoder.
- * \param  client_data  The callee's client data set through
- *                      FLAC__file_decoder_set_client_data().
- */
-typedef void (*FLAC__FileDecoderErrorCallback)(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-/** Create a new file decoder instance.  The instance is created with
- *  default settings; see the individual FLAC__file_decoder_set_*()
- *  functions for each setting's default.
- *
- * \retval FLAC__FileDecoder*
- *    \c NULL if there was an error allocating memory, else the new instance.
- */
-FLAC_API FLAC__FileDecoder *FLAC__file_decoder_new();
-
-/** Free a decoder instance.  Deletes the object pointed to by \a decoder.
- *
- * \param decoder  A pointer to an existing decoder.
- * \assert
- *    \code decoder != NULL \endcode
- */
-FLAC_API void FLAC__file_decoder_delete(FLAC__FileDecoder *decoder);
-
-
-/***********************************************************************
- *
- * Public class method prototypes
- *
- ***********************************************************************/
-
-/** Set the "MD5 signature checking" flag.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_md5_checking().
- *
- * \default \c false
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_md5_checking(FLAC__FileDecoder *decoder, FLAC__bool value);
-
-/** Set the input file name to decode.
- *
- * \default \c "-"
- * \param  decoder  A decoder instance to set.
- * \param  value    The input file name, or "-" for \c stdin.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, or there was a memory
- *    allocation error, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_filename(FLAC__FileDecoder *decoder, const char *value);
-
-/** Set the write callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_write_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_write_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderWriteCallback value);
-
-/** Set the metadata callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderMetadataCallback value);
-
-/** Set the error callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_error_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_error_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderErrorCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_client_data(FLAC__FileDecoder *decoder, void *value);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_respond().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  type     See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \a type is valid
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond(FLAC__FileDecoder *decoder, FLAC__MetadataType type);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_respond_application().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  id       See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code id != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond_application(FLAC__FileDecoder *decoder, const FLAC__byte id[4]);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_respond_all().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond_all(FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_ignore().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  type     See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \a type is valid
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore(FLAC__FileDecoder *decoder, FLAC__MetadataType type);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_ignore_application().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  id       See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code id != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore_application(FLAC__FileDecoder *decoder, const FLAC__byte id[4]);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_ignore_all().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore_all(FLAC__FileDecoder *decoder);
-
-/** Get the current decoder state.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__FileDecoderState
- *    The current decoder state.
- */
-FLAC_API FLAC__FileDecoderState FLAC__file_decoder_get_state(const FLAC__FileDecoder *decoder);
-
-/** Get the state of the underlying seekable stream decoder.
- *  Useful when the file decoder state is
- *  \c FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__SeekableStreamDecoderState
- *    The seekable stream decoder state.
- */
-FLAC_API FLAC__SeekableStreamDecoderState FLAC__file_decoder_get_seekable_stream_decoder_state(const FLAC__FileDecoder *decoder);
-
-/** Get the state of the underlying stream decoder.
- *  Useful when the file decoder state is
- *  \c FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR and the seekable stream
- *  decoder state is \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    The seekable stream decoder state.
- */
-FLAC_API FLAC__StreamDecoderState FLAC__file_decoder_get_stream_decoder_state(const FLAC__FileDecoder *decoder);
-
-/** Get the current decoder state as a C string.
- *  This version automatically resolves
- *  \c FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR by getting the
- *  seekable stream decoder's state.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval const char *
- *    The decoder state as a C string.  Do not modify the contents.
- */
-FLAC_API const char *FLAC__file_decoder_get_resolved_state_string(const FLAC__FileDecoder *decoder);
-
-/** Get the "MD5 signature checking" flag.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_md5_checking().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_get_md5_checking(const FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_channels().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-FLAC_API unsigned FLAC__file_decoder_get_channels(const FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_channel_assignment().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__ChannelAssignment
- *    See above.
- */
-FLAC_API FLAC__ChannelAssignment FLAC__file_decoder_get_channel_assignment(const FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_bits_per_sample().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-FLAC_API unsigned FLAC__file_decoder_get_bits_per_sample(const FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_sample_rate().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-FLAC_API unsigned FLAC__file_decoder_get_sample_rate(const FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_blocksize().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-FLAC_API unsigned FLAC__file_decoder_get_blocksize(const FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_decode_position().
- *
- * \param  decoder   A decoder instance to query.
- * \param  position  Address at which to return the desired position.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code position != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, \c false if there was an error from
- *    the 'tell' callback.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_get_decode_position(const FLAC__FileDecoder *decoder, FLAC__uint64 *position);
-
-/** Initialize the decoder instance.
- *  Should be called after FLAC__file_decoder_new() and
- *  FLAC__file_decoder_set_*() but before any of the
- *  FLAC__file_decoder_process_*() functions.  Will set and return
- *  the decoder state, which will be FLAC__FILE_DECODER_OK if
- *  initialization succeeded.
- *
- * \param  decoder  An uninitialized decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__FileDecoderState
- *    \c FLAC__FILE_DECODER_OK if initialization was successful; see
- *    FLAC__FileDecoderState for the meanings of other return values.
- */
-FLAC_API FLAC__FileDecoderState FLAC__file_decoder_init(FLAC__FileDecoder *decoder);
-
-/** Finish the decoding process.
- *  Flushes the decoding buffer, releases resources, resets the decoder
- *  settings to their defaults, and returns the decoder state to
- *  FLAC__FILE_DECODER_UNINITIALIZED.
- *
- *  In the event of a prematurely-terminated decode, it is not strictly
- *  necessary to call this immediately before FLAC__file_decoder_delete()
- *  but it is good practice to match every FLAC__file_decoder_init() with
- *  a FLAC__file_decoder_finish().
- *
- * \param  decoder  An uninitialized decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if MD5 checking is on AND a STREAMINFO block was available
- *    AND the MD5 signature in the STREAMINFO block was non-zero AND the
- *    signature does not match the one computed by the decoder; else
- *    \c true.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_finish(FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_process_single().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_process_single(FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_process_until_end_of_metadata().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_metadata(FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_process_until_end_of_stream().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_file(FLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_skip_single_frame().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_skip_single_frame(FLAC__FileDecoder *decoder);
-
-/** Flush the input and seek to an absolute sample.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_seek_absolute().
- *
- * \param  decoder  A decoder instance.
- * \param  sample   The target sample number to seek to.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false.
- */
-FLAC_API FLAC__bool FLAC__file_decoder_seek_absolute(FLAC__FileDecoder *decoder, FLAC__uint64 sample);
-
-/* \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/FLAC/file_encoder.h b/include/FLAC/file_encoder.h
deleted file mode 100644 (file)
index e0e206d..0000000
+++ /dev/null
@@ -1,886 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLAC__FILE_ENCODER_H
-#define FLAC__FILE_ENCODER_H
-
-#include "export.h"
-#include "seekable_stream_encoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** \file include/FLAC/file_encoder.h
- *
- *  \brief
- *  This module contains the functions which implement the file
- *  encoder.
- *
- *  See the detailed documentation in the
- *  \link flac_file_encoder file encoder \endlink module.
- */
-
-/** \defgroup flac_file_encoder FLAC/file_encoder.h: file encoder interface
- *  \ingroup flac_encoder
- *
- *  \brief
- *  This module contains the functions which implement the file
- *  encoder.
- *
- * The basic usage of this encoder is as follows:
- * - The program creates an instance of an encoder using
- *   FLAC__file_encoder_new().
- * - The program overrides the default settings using
- *   FLAC__file_encoder_set_*() functions.
- * - The program initializes the instance to validate the settings and
- *   prepare for encoding using FLAC__file_encoder_init().
- * - The program calls FLAC__file_encoder_process() or
- *   FLAC__file_encoder_process_interleaved() to encode data, which
- *   subsequently writes data to the output file.
- * - The program finishes the encoding with FLAC__file_encoder_finish(),
- *   which causes the encoder to encode any data still in its input pipe,
- *   rewind and write the STREAMINFO metadata to file, and finally reset
- *   the encoder to the uninitialized state.
- * - The instance may be used again or deleted with
- *   FLAC__file_encoder_delete().
- *
- * The file encoder is a wrapper around the
- * \link flac_seekable_stream_encoder seekable stream encoder \endlink which supplies all
- * callbacks internally; the user need specify only the filename.
- *
- * Make sure to read the detailed description of the
- * \link flac_seekable_stream_encoder seekable stream encoder module \endlink since the
- * \link flac_stream_encoder stream encoder module \endlink since the
- * file encoder inherits much of its behavior from them.
- *
- * \note
- * The "set" functions may only be called when the encoder is in the
- * state FLAC__FILE_ENCODER_UNINITIALIZED, i.e. after
- * FLAC__file_encoder_new() or FLAC__file_encoder_finish(), but
- * before FLAC__file_encoder_init().  If this is the case they will
- * return \c true, otherwise \c false.
- *
- * \note
- * FLAC__file_encoder_finish() resets all settings to the constructor
- * defaults.
- *
- * \{
- */
-
-
-/** State values for a FLAC__FileEncoder
- *
- *  The encoder's state can be obtained by calling FLAC__file_encoder_get_state().
- */
-typedef enum {
-
-       FLAC__FILE_ENCODER_OK = 0,
-       /**< The encoder is in the normal OK state. */
-
-       FLAC__FILE_ENCODER_NO_FILENAME,
-       /**< FLAC__file_encoder_init() was called without first calling
-        * FLAC__file_encoder_set_filename().
-        */
-
-       FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR,
-       /**< An error occurred in the underlying seekable stream encoder;
-        * check FLAC__file_encoder_get_seekable_stream_encoder_state().
-        */
-
-       FLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING,
-       /**< A fatal error occurred while writing to the encoded file. */
-
-       FLAC__FILE_ENCODER_ERROR_OPENING_FILE,
-       /**< An error occurred opening the output file for writing. */
-
-       FLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
-
-       FLAC__FILE_ENCODER_ALREADY_INITIALIZED,
-       /**< FLAC__file_encoder_init() was called when the encoder was
-        * already initialized, usually because
-        * FLAC__file_encoder_finish() was not called.
-        */
-
-       FLAC__FILE_ENCODER_UNINITIALIZED
-       /**< The encoder is in the uninitialized state. */
-
-} FLAC__FileEncoderState;
-
-/** Maps a FLAC__FileEncoderState to a C string.
- *
- *  Using a FLAC__FileEncoderState as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__FileEncoderStateString[];
-
-
-/***********************************************************************
- *
- * class FLAC__FileEncoder
- *
- ***********************************************************************/
-
-struct FLAC__FileEncoderProtected;
-struct FLAC__FileEncoderPrivate;
-/** The opaque structure definition for the file encoder type.
- *  See the \link flac_file_encoder file encoder module \endlink
- *  for a detailed description.
- */
-typedef struct {
-       struct FLAC__FileEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */
-       struct FLAC__FileEncoderPrivate *private_; /* avoid the C++ keyword 'private' */
-} FLAC__FileEncoder;
-
-/** Signature for the progress callback.
- *  See FLAC__file_encoder_set_progress_callback() for more info.
- *
- * \param  encoder          The encoder instance calling the callback.
- * \param  bytes_written    Bytes written so far.
- * \param  samples_written  Samples written so far.
- * \param  frames_written   Frames written so far.
- * \param  total_frames_estimate  The estimate of the total number of
- *                                frames to be written.
- * \param  client_data      The callee's client data set through
- *                          FLAC__file_encoder_set_client_data().
- */
-typedef void (*FLAC__FileEncoderProgressCallback)(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-/** Create a new file encoder instance.  The instance is created with
- *  default settings; see the individual FLAC__file_encoder_set_*()
- *  functions for each setting's default.
- *
- * \retval FLAC__FileEncoder*
- *    \c NULL if there was an error allocating memory, else the new instance.
- */
-FLAC_API FLAC__FileEncoder *FLAC__file_encoder_new();
-
-/** Free an encoder instance.  Deletes the object pointed to by \a encoder.
- *
- * \param encoder  A pointer to an existing encoder.
- * \assert
- *    \code encoder != NULL \endcode
- */
-FLAC_API void FLAC__file_encoder_delete(FLAC__FileEncoder *encoder);
-
-/***********************************************************************
- *
- * Public class method prototypes
- *
- ***********************************************************************/
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_verify().
- *
- * \default \c true
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_verify(FLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_streamable_subset().
- *
- * \default \c true
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_streamable_subset(FLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_do_mid_side_stereo().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_do_mid_side_stereo(FLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_loose_mid_side_stereo().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_loose_mid_side_stereo(FLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_channels().
- *
- * \default \c 2
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_channels(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_bits_per_sample().
- *
- * \warning
- * Do not feed the encoder data that is wider than the value you
- * set here or you will generate an invalid stream.
- *
- * \default \c 16
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_bits_per_sample(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_sample_rate().
- *
- * \default \c 44100
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_sample_rate(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_blocksize().
- *
- * \default \c 1152
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_blocksize(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_apodization().
- *
- * \default \c 0
- * \param  encoder        An encoder instance to set.
- * \param  specification  See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code specification != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-/* @@@@add to unit tests*/
-FLAC_API FLAC__bool FLAC__file_encoder_set_apodization(FLAC__FileEncoder *encoder, const char *specification);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_max_lpc_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_max_lpc_order(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_qlp_coeff_precision().
- *
- * \note
- * In the current implementation, qlp_coeff_precision + bits_per_sample must
- * be less than 32.
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_qlp_coeff_precision(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_do_qlp_coeff_prec_search(FLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_do_escape_coding().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_do_escape_coding(FLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_do_exhaustive_model_search().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_do_exhaustive_model_search(FLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_min_residual_partition_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_min_residual_partition_order(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_max_residual_partition_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_max_residual_partition_order(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_rice_parameter_search_dist().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_rice_parameter_search_dist(FLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_total_samples_estimate().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_total_samples_estimate(FLAC__FileEncoder *encoder, FLAC__uint64 value);
-
-/** This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_set_metadata().
- *
- * \default \c NULL, 0
- * \param  encoder     An encoder instance to set.
- * \param  metadata    See above.
- * \param  num_blocks  See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_metadata(FLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
-
-/** Set the output file name encode to.
- *
- * \note
- * The filename is mandatory and must be set before initialization.
- *
- * \note
- * Unlike the FLAC__FileDecoder, the filename does not interpret "-" for
- * \c stdout; writing to \c stdout is not relevant in the file encoder.
- *
- * \default \c NULL
- * \param  encoder  A encoder instance to set.
- * \param  value    The output file name.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, or there was a memory
- *    allocation error, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_filename(FLAC__FileEncoder *encoder, const char *value);
-
-/** Set the progress callback.
- *  The supplied function will be called when the encoder has finished
- *  writing a frame.  The \c total_frames_estimate argument to the callback
- *  will be based on the value from
- *  FLAC__file_encoder_set_total_samples_estimate().
- *
- * \note
- * Unlike most other callbacks, the progress callback is \b not mandatory
- * and need not be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_progress_callback(FLAC__FileEncoder *encoder, FLAC__FileEncoderProgressCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_set_client_data(FLAC__FileEncoder *encoder, void *value);
-
-/** Get the current encoder state.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__FileEncoderState
- *    The current encoder state.
- */
-FLAC_API FLAC__FileEncoderState FLAC__file_encoder_get_state(const FLAC__FileEncoder *encoder);
-
-/** Get the state of the underlying seekable stream encoder.
- *  Useful when the file encoder state is
- *  \c FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__SeekableStreamEncoderState
- *    The seekable stream encoder state.
- */
-FLAC_API FLAC__SeekableStreamEncoderState FLAC__file_encoder_get_seekable_stream_encoder_state(const FLAC__FileEncoder *encoder);
-
-/** Get the state of the underlying stream encoder.
- *  Useful when the file encoder state is
- *  \c FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR and the seekable stream
- *  encoder state is \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__StreamEncoderState
- *    The seekable stream encoder state.
- */
-FLAC_API FLAC__StreamEncoderState FLAC__file_encoder_get_stream_encoder_state(const FLAC__FileEncoder *encoder);
-
-/** Get the state of the underlying stream encoder's verify decoder.
- *  Useful when the file encoder state is
- *  \c FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR and the seekable stream
- *  encoder state is \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR and
- *  the stream encoder state is \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    The stream encoder state.
- */
-FLAC_API FLAC__StreamDecoderState FLAC__file_encoder_get_verify_decoder_state(const FLAC__FileEncoder *encoder);
-
-/** Get the current encoder state as a C string.
- *  This version automatically resolves
- *  \c FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR by getting the
- *  seekable stream encoder's state.
- *
- * \param  encoder  A encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval const char *
- *    The encoder state as a C string.  Do not modify the contents.
- */
-FLAC_API const char *FLAC__file_encoder_get_resolved_state_string(const FLAC__FileEncoder *encoder);
-
-/** Get relevant values about the nature of a verify decoder error.
- *  Inherited from FLAC__seekable_stream_encoder_get_verify_decoder_error_stats().
- *  Useful when the file encoder state is
- *  \c FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR and the seekable stream
- *  encoder state is
- *  \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR and the
- *  stream encoder state is
- *  \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \param  absolute_sample  The absolute sample number of the mismatch.
- * \param  frame_number  The number of the frame in which the mismatch occurred.
- * \param  channel       The channel in which the mismatch occurred.
- * \param  sample        The number of the sample (relative to the frame) in
- *                       which the mismatch occurred.
- * \param  expected      The expected value for the sample in question.
- * \param  got           The actual value returned by the decoder.
- * \assert
- *    \code encoder != NULL \endcode
- */
-FLAC_API void FLAC__file_encoder_get_verify_decoder_error_stats(const FLAC__FileEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-
-/** Get the "verify" flag.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_verify().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__file_encoder_set_verify().
- */
-FLAC_API FLAC__bool FLAC__file_encoder_get_verify(const FLAC__FileEncoder *encoder);
-
-/** Get the "streamable subset" flag.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_streamable_subset().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__file_encoder_set_streamable_subset().
- */
-FLAC_API FLAC__bool FLAC__file_encoder_get_streamable_subset(const FLAC__FileEncoder *encoder);
-
-/** Get the "mid/side stereo coding" flag.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_do_mid_side_stereo().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__file_encoder_get_do_mid_side_stereo().
- */
-FLAC_API FLAC__bool FLAC__file_encoder_get_do_mid_side_stereo(const FLAC__FileEncoder *encoder);
-
-/** Get the "adaptive mid/side switching" flag.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_loose_mid_side_stereo().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__file_encoder_set_loose_mid_side_stereo().
- */
-FLAC_API FLAC__bool FLAC__file_encoder_get_loose_mid_side_stereo(const FLAC__FileEncoder *encoder);
-
-/** Get the number of input channels being processed.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_channels().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_channels().
- */
-FLAC_API unsigned FLAC__file_encoder_get_channels(const FLAC__FileEncoder *encoder);
-
-/** Get the input sample resolution setting.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_bits_per_sample().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_bits_per_sample().
- */
-FLAC_API unsigned FLAC__file_encoder_get_bits_per_sample(const FLAC__FileEncoder *encoder);
-
-/** Get the input sample rate setting.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_sample_rate().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_sample_rate().
- */
-FLAC_API unsigned FLAC__file_encoder_get_sample_rate(const FLAC__FileEncoder *encoder);
-
-/** Get the blocksize setting.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_blocksize().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_blocksize().
- */
-FLAC_API unsigned FLAC__file_encoder_get_blocksize(const FLAC__FileEncoder *encoder);
-
-/** Get the maximum LPC order setting.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_max_lpc_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_max_lpc_order().
- */
-FLAC_API unsigned FLAC__file_encoder_get_max_lpc_order(const FLAC__FileEncoder *encoder);
-
-/** Get the quantized linear predictor coefficient precision setting.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_qlp_coeff_precision().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_qlp_coeff_precision().
- */
-FLAC_API unsigned FLAC__file_encoder_get_qlp_coeff_precision(const FLAC__FileEncoder *encoder);
-
-/** Get the qlp coefficient precision search flag.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__file_encoder_set_do_qlp_coeff_prec_search().
- */
-FLAC_API FLAC__bool FLAC__file_encoder_get_do_qlp_coeff_prec_search(const FLAC__FileEncoder *encoder);
-
-/** Get the "escape coding" flag.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_do_escape_coding().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__file_encoder_set_do_escape_coding().
- */
-FLAC_API FLAC__bool FLAC__file_encoder_get_do_escape_coding(const FLAC__FileEncoder *encoder);
-
-/** Get the exhaustive model search flag.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_do_exhaustive_model_search().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__file_encoder_set_do_exhaustive_model_search().
- */
-FLAC_API FLAC__bool FLAC__file_encoder_get_do_exhaustive_model_search(const FLAC__FileEncoder *encoder);
-
-/** Get the minimum residual partition order setting.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_min_residual_partition_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_min_residual_partition_order().
- */
-FLAC_API unsigned FLAC__file_encoder_get_min_residual_partition_order(const FLAC__FileEncoder *encoder);
-
-/** Get maximum residual partition order setting.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_max_residual_partition_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_max_residual_partition_order().
- */
-FLAC_API unsigned FLAC__file_encoder_get_max_residual_partition_order(const FLAC__FileEncoder *encoder);
-
-/** Get the Rice parameter search distance setting.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_rice_parameter_search_dist().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_rice_parameter_search_dist().
- */
-FLAC_API unsigned FLAC__file_encoder_get_rice_parameter_search_dist(const FLAC__FileEncoder *encoder);
-
-/** Get the previously set estimate of the total samples to be encoded.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_get_total_samples_estimate().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__uint64
- *    See FLAC__file_encoder_set_total_samples_estimate().
- */
-FLAC_API FLAC__uint64 FLAC__file_encoder_get_total_samples_estimate(const FLAC__FileEncoder *encoder);
-
-/** Initialize the encoder instance.
- *  Should be called after FLAC__file_encoder_new() and
- *  FLAC__file_encoder_set_*() but before FLAC__file_encoder_process()
- *  or FLAC__file_encoder_process_interleaved().  Will set and return
- *  the encoder state, which will be FLAC__FILE_ENCODER_OK if
- *  initialization succeeded.
- *
- * \param  encoder  An uninitialized encoder instance.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__FileEncoderState
- *    \c FLAC__FILE_ENCODER_OK if initialization was successful; see
- *    FLAC__FileEncoderState for the meanings of other return values.
- */
-FLAC_API FLAC__FileEncoderState FLAC__file_encoder_init(FLAC__FileEncoder *encoder);
-
-/** Finish the encoding process.
- *  Flushes the encoding buffer, releases resources, resets the encoder
- *  settings to their defaults, and returns the encoder state to
- *  FLAC__FILE_ENCODER_UNINITIALIZED.
- *
- *  In the event of a prematurely-terminated encode, it is not strictly
- *  necessary to call this immediately before FLAC__file_encoder_delete()
- *  but it is good practice to match every FLAC__file_encoder_init()
- *  with a FLAC__file_encoder_finish().
- *
- * \param  encoder  An uninitialized encoder instance.
- * \assert
- *    \code encoder != NULL \endcode
- */
-FLAC_API void FLAC__file_encoder_finish(FLAC__FileEncoder *encoder);
-
-/** Submit data for encoding.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_process().
- *
- * \param  encoder  An initialized encoder instance in the OK state.
- * \param  buffer   An array of pointers to each channel's signal.
- * \param  samples  The number of samples in one channel.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code FLAC__file_encoder_get_state(encoder) == FLAC__FILE_ENCODER_OK \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false; in this case, check the
- *    encoder state with FLAC__file_encoder_get_state() to see what
- *    went wrong.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_process(FLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples);
-
-/** Submit data for encoding.
- *  This is inherited from FLAC__SeekableStreamEncoder; see
- *  FLAC__seekable_stream_encoder_process_interleaved().
- *
- * \param  encoder  An initialized encoder instance in the OK state.
- * \param  buffer   An array of channel-interleaved data (see above).
- * \param  samples  The number of samples in one channel, the same as for
- *                  FLAC__file_encoder_process().  For example, if
- *                  encoding two channels, \c 1000 \a samples corresponds
- *                  to a \a buffer of 2000 values.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code FLAC__file_encoder_get_state(encoder) == FLAC__FILE_ENCODER_OK \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false; in this case, check the
- *    encoder state with FLAC__file_encoder_get_state() to see what
- *    went wrong.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_process_interleaved(FLAC__FileEncoder *encoder, const FLAC__int32 buffer[], unsigned samples);
-
-/* \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
index 5979a00..e5799de 100644 (file)
@@ -1338,11 +1338,40 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC_
  * \assert
  *    \code object != NULL \endcode
  *    \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode
+ *    \code total_samples > 0 \endcode
  * \retval FLAC__bool
  *    \c false if memory allocation fails, else \c true.
  */
 FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, unsigned num, FLAC__uint64 total_samples);
 
+/** Append a set of evenly-spaced seek point templates to the end of a
+ *  seek table.
+ *
+ * \note
+ * As with the other ..._seektable_template_... functions, you should
+ * call FLAC__metadata_object_seektable_template_sort() when finished
+ * to make the seek table legal.
+ *
+ * \param object  A pointer to an existing SEEKTABLE object.
+ * \param samples The number of samples apart to space the placeholder
+ *                points.  The first point will be at sample \c 0, the
+ *                second at sample \a samples, then 2*\a samples, and
+ *                so on.  As long as \a samples and \a total_samples
+ *                are greater than \c 0, there will always be at least
+ *                one seekpoint at sample \0.
+ * \param total_samples  The total number of samples to be encoded;
+ *                       the seekpoints will be spaced
+ *                       \a samples samples apart.
+ * \assert
+ *    \code object != NULL \endcode
+ *    \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode
+ *    \code samples > 0 \endcode
+ *    \code total_samples > 0 \endcode
+ * \retval FLAC__bool
+ *    \c false if memory allocation fails, else \c true.
+ */
+FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples);
+
 /** Sort a seek table's seek points according to the format specification,
  *  removing duplicates.
  *
diff --git a/include/FLAC/seekable_stream_decoder.h b/include/FLAC/seekable_stream_decoder.h
deleted file mode 100644 (file)
index 336f830..0000000
+++ /dev/null
@@ -1,931 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006 Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLAC__SEEKABLE_STREAM_DECODER_H
-#define FLAC__SEEKABLE_STREAM_DECODER_H
-
-#include "export.h"
-#include "stream_decoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** \file include/FLAC/seekable_stream_decoder.h
- *
- *  \brief
- *  This module contains the functions which implement the seekable stream
- *  decoder.
- *
- *  See the detailed documentation in the
- *  \link flac_seekable_stream_decoder seekable stream decoder \endlink module.
- */
-
-/** \defgroup flac_seekable_stream_decoder FLAC/seekable_stream_decoder.h: seekable stream decoder interface
- *  \ingroup flac_decoder
- *
- *  \brief
- *  This module contains the functions which implement the seekable stream
- *  decoder.
- *
- * The basic usage of this decoder is as follows:
- * - The program creates an instance of a decoder using
- *   FLAC__seekable_stream_decoder_new().
- * - The program overrides the default settings and sets callbacks for
- *   reading, writing, seeking, error reporting, and metadata reporting
- *   using FLAC__seekable_stream_decoder_set_*() functions.
- * - The program initializes the instance to validate the settings and
- *   prepare for decoding using FLAC__seekable_stream_decoder_init().
- * - The program calls the FLAC__seekable_stream_decoder_process_*()
- *   functions to decode data, which subsequently calls the callbacks.
- * - The program finishes the decoding with
- *   FLAC__seekable_stream_decoder_finish(), which flushes the input and
- *   output and resets the decoder to the uninitialized state.
- * - The instance may be used again or deleted with
- *   FLAC__seekable_stream_decoder_delete().
- *
- * The seekable stream decoder is a wrapper around the
- * \link flac_stream_decoder stream decoder \endlink which also provides
- * seeking capability.  In addition to the Read/Write/Metadata/Error
- * callbacks of the stream decoder, the user must also provide the following:
- *
- * - Seek callback - This function will be called when the decoder wants to
- *   seek to an absolute position in the stream.
- * - Tell callback - This function will be called when the decoder wants to
- *   know the current absolute position of the stream.
- * - Length callback - This function will be called when the decoder wants
- *   to know length of the stream.  The seeking algorithm currently requires
- *   that the overall stream length be known.
- * - EOF callback - This function will be called when the decoder wants to
- *   know if it is at the end of the stream.  This could be synthesized from
- *   the tell and length callbacks but it may be more expensive that way, so
- *   there is a separate callback for it.
- *
- * Seeking is exposed through the
- * FLAC__seekable_stream_decoder_seek_absolute() method.  At any point after
- * the seekable stream decoder has been initialized, the user can call this
- * function to seek to an exact sample within the stream.  Subsequently, the
- * first time the write callback is called it will be passed a (possibly
- * partial) block starting at that sample.
- *
- * The seekable stream decoder also provides MD5 signature checking.  If
- * this is turned on before initialization,
- * FLAC__seekable_stream_decoder_finish() will report when the decoded MD5
- * signature does not match the one stored in the STREAMINFO block.  MD5
- * checking is automatically turned off (until the next
- * FLAC__seekable_stream_decoder_reset()) if there is no signature in the
- * STREAMINFO block or when a seek is attempted.
- *
- * Make sure to read the detailed description of the
- * \link flac_stream_decoder stream decoder module \endlink since the
- * seekable stream decoder inherits much of its behavior.
- *
- * \note
- * The "set" functions may only be called when the decoder is in the
- * state FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED, i.e. after
- * FLAC__seekable_stream_decoder_new() or
- * FLAC__seekable_stream_decoder_finish(), but before
- * FLAC__seekable_stream_decoder_init().  If this is the case they will
- * return \c true, otherwise \c false.
- *
- * \note
- * FLAC__stream_decoder_finish() resets all settings to the constructor
- * defaults, including the callbacks.
- *
- * \{
- */
-
-
-/** State values for a FLAC__SeekableStreamDecoder
- *
- *  The decoder's state can be obtained by calling FLAC__seekable_stream_decoder_get_state().
- */
-typedef enum {
-
-       FLAC__SEEKABLE_STREAM_DECODER_OK = 0,
-       /**< The decoder is in the normal OK state. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_SEEKING,
-       /**< The decoder is in the process of seeking. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM,
-       /**< The decoder has reached the end of the stream. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
-       /**< An error occurred allocating memory. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR,
-       /**< An error occurred in the underlying stream decoder. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR,
-       /**< The read callback returned an error. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR,
-       /**< An error occurred while seeking or the seek or tell
-        * callback returned an error.
-        */
-
-       FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED,
-       /**< FLAC__seekable_stream_decoder_init() was called when the
-        * decoder was already initialized, usually because
-        * FLAC__seekable_stream_decoder_finish() was not called.
-        */
-
-       FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK,
-       /**< FLAC__seekable_stream_decoder_init() was called without all
-        * callbacks being set.
-        */
-
-       FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED
-       /**< The decoder is in the uninitialized state. */
-
-} FLAC__SeekableStreamDecoderState;
-
-/** Maps a FLAC__SeekableStreamDecoderState to a C string.
- *
- *  Using a FLAC__SeekableStreamDecoderState as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__SeekableStreamDecoderStateString[];
-
-
-/** Return values for the FLAC__SeekableStreamDecoder read callback.
- */
-typedef enum {
-
-       FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK,
-       /**< The read was OK and decoding can continue. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR
-       /**< An unrecoverable error occurred.  The decoder will return from the process call. */
-
-} FLAC__SeekableStreamDecoderReadStatus;
-
-/** Maps a FLAC__SeekableStreamDecoderReadStatus to a C string.
- *
- *  Using a FLAC__SeekableStreamDecoderReadStatus as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__SeekableStreamDecoderReadStatusString[];
-
-
-/** Return values for the FLAC__SeekableStreamDecoder seek callback.
- */
-typedef enum {
-
-       FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK,
-       /**< The seek was OK and decoding can continue. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR
-       /**< An unrecoverable error occurred.  The decoder will return from the process call. */
-
-} FLAC__SeekableStreamDecoderSeekStatus;
-
-/** Maps a FLAC__SeekableStreamDecoderSeekStatus to a C string.
- *
- *  Using a FLAC__SeekableStreamDecoderSeekStatus as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__SeekableStreamDecoderSeekStatusString[];
-
-
-/** Return values for the FLAC__SeekableStreamDecoder tell callback.
- */
-typedef enum {
-
-       FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK,
-       /**< The tell was OK and decoding can continue. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR
-       /**< An unrecoverable error occurred.  The decoder will return from the process call. */
-
-} FLAC__SeekableStreamDecoderTellStatus;
-
-/** Maps a FLAC__SeekableStreamDecoderTellStatus to a C string.
- *
- *  Using a FLAC__SeekableStreamDecoderTellStatus as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__SeekableStreamDecoderTellStatusString[];
-
-
-/** Return values for the FLAC__SeekableStreamDecoder length callback.
- */
-typedef enum {
-
-       FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK,
-       /**< The length call was OK and decoding can continue. */
-
-       FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR
-       /**< An unrecoverable error occurred.  The decoder will return from the process call. */
-
-} FLAC__SeekableStreamDecoderLengthStatus;
-
-/** Maps a FLAC__SeekableStreamDecoderLengthStatus to a C string.
- *
- *  Using a FLAC__SeekableStreamDecoderLengthStatus as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__SeekableStreamDecoderLengthStatusString[];
-
-
-/***********************************************************************
- *
- * class FLAC__SeekableStreamDecoder : public FLAC__StreamDecoder
- *
- ***********************************************************************/
-
-struct FLAC__SeekableStreamDecoderProtected;
-struct FLAC__SeekableStreamDecoderPrivate;
-/** The opaque structure definition for the seekable stream decoder type.
- *  See the
- *  \link flac_seekable_stream_decoder seekable stream decoder module \endlink
- *  for a detailed description.
- */
-typedef struct {
-       struct FLAC__SeekableStreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */
-       struct FLAC__SeekableStreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */
-} FLAC__SeekableStreamDecoder;
-
-/** Signature for the read callback.
- *  See FLAC__seekable_stream_decoder_set_read_callback()
- *  and FLAC__StreamDecoderReadCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  buffer   A pointer to a location for the callee to store
- *                  data to be decoded.
- * \param  bytes    A pointer to the size of the buffer.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__SeekableStreamDecoderReadStatus
- *    The callee's return status.
- */
-typedef FLAC__SeekableStreamDecoderReadStatus (*FLAC__SeekableStreamDecoderReadCallback)(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-
-/** Signature for the seek callback.
- *  See FLAC__seekable_stream_decoder_set_seek_callback() for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  absolute_byte_offset  The offset from the beginning of the stream
- *                               to seek to.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__SeekableStreamDecoderSeekStatus
- *    The callee's return status.
- */
-typedef FLAC__SeekableStreamDecoderSeekStatus (*FLAC__SeekableStreamDecoderSeekCallback)(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-
-/** Signature for the tell callback.
- *  See FLAC__seekable_stream_decoder_set_tell_callback() for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  absolute_byte_offset  A pointer to storage for the current offset
- *                               from the beginning of the stream.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__SeekableStreamDecoderTellStatus
- *    The callee's return status.
- */
-typedef FLAC__SeekableStreamDecoderTellStatus (*FLAC__SeekableStreamDecoderTellCallback)(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-
-/** Signature for the length callback.
- *  See FLAC__seekable_stream_decoder_set_length_callback() for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  stream_length  A pointer to storage for the length of the stream
- *                        in bytes.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__SeekableStreamDecoderLengthStatus
- *    The callee's return status.
- */
-typedef FLAC__SeekableStreamDecoderLengthStatus (*FLAC__SeekableStreamDecoderLengthCallback)(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
-
-/** Signature for the EOF callback.
- *  See FLAC__seekable_stream_decoder_set_eof_callback() for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__bool
- *    \c true if the currently at the end of the stream, else \c false.
- */
-typedef FLAC__bool (*FLAC__SeekableStreamDecoderEofCallback)(const FLAC__SeekableStreamDecoder *decoder, void *client_data);
-
-/** Signature for the write callback.
- *  See FLAC__seekable_stream_decoder_set_write_callback()
- *  and FLAC__StreamDecoderWriteCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  frame    The description of the decoded frame.
- * \param  buffer   An array of pointers to decoded channels of data.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__StreamDecoderWriteStatus
- *    The callee's return status.
- */
-typedef FLAC__StreamDecoderWriteStatus (*FLAC__SeekableStreamDecoderWriteCallback)(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-
-/** Signature for the metadata callback.
- *  See FLAC__seekable_stream_decoder_set_metadata_callback()
- *  and FLAC__StreamDecoderMetadataCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  metadata The decoded metadata block.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_decoder_set_client_data().
- */
-typedef void (*FLAC__SeekableStreamDecoderMetadataCallback)(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-
-/** Signature for the error callback.
- *  See FLAC__seekable_stream_decoder_set_error_callback()
- *  and FLAC__StreamDecoderErrorCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  status   The error encountered by the decoder.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_decoder_set_client_data().
- */
-typedef void (*FLAC__SeekableStreamDecoderErrorCallback)(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-/** Create a new seekable stream decoder instance.  The instance is created
- *  with default settings; see the individual
- *  FLAC__seekable_stream_decoder_set_*() functions for each setting's
- *  default.
- *
- * \retval FLAC__SeekableStreamDecoder*
- *    \c NULL if there was an error allocating memory, else the new instance.
- */
-FLAC_API FLAC__SeekableStreamDecoder *FLAC__seekable_stream_decoder_new();
-
-/** Free a decoder instance.  Deletes the object pointed to by \a decoder.
- *
- * \param decoder  A pointer to an existing decoder.
- * \assert
- *    \code decoder != NULL \endcode
- */
-FLAC_API void FLAC__seekable_stream_decoder_delete(FLAC__SeekableStreamDecoder *decoder);
-
-
-/***********************************************************************
- *
- * Public class method prototypes
- *
- ***********************************************************************/
-
-/** Set the "MD5 signature checking" flag.  If \c true, the decoder will
- *  compute the MD5 signature of the unencoded audio data while decoding
- *  and compare it to the signature from the STREAMINFO block, if it
- *  exists, during FLAC__seekable_stream_decoder_finish().
- *
- *  MD5 signature checking will be turned off (until the next
- *  FLAC__seekable_stream_decoder_reset()) if there is no signature in
- *  the STREAMINFO block or when a seek is attempted.
- *
- * \default \c false
- * \param  decoder  A decoder instance to set.
- * \param  value    Flag value (see above).
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_md5_checking(FLAC__SeekableStreamDecoder *decoder, FLAC__bool value);
-
-/** Set the read callback.
- *  This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_read_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_read_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderReadCallback value);
-
-/** Set the seek callback.
- *  The supplied function will be called when the decoder needs to seek
- *  the input stream.  The decoder will pass the absolute byte offset
- *  to seek to, 0 meaning the beginning of the stream.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_seek_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderSeekCallback value);
-
-/** Set the tell callback.
- *  The supplied function will be called when the decoder wants to know
- *  the current position of the stream.  The callback should return the
- *  byte offset from the beginning of the stream.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_tell_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderTellCallback value);
-
-/** Set the length callback.
- *  The supplied function will be called when the decoder wants to know
- *  the total length of the stream in bytes.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_length_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderLengthCallback value);
-
-/** Set the eof callback.
- *  The supplied function will be called when the decoder needs to know
- *  if the end of the stream has been reached.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_eof_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderEofCallback value);
-
-/** Set the write callback.
- *  This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_write_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_write_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderWriteCallback value);
-
-/** Set the metadata callback.
- *  This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_metadata_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderMetadataCallback value);
-
-/** Set the error callback.
- *  This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_error_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_error_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderErrorCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_client_data(FLAC__SeekableStreamDecoder *decoder, void *value);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_metadata_respond().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  type     See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \a type is valid
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond(FLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_metadata_respond_application().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  id       See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code id != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond_application(FLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4]);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_metadata_respond_all().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond_all(FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_metadata_ignore().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  type     See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \a type is valid
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore(FLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_metadata_ignore_application().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  id       See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code id != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore_application(FLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4]);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_set_metadata_ignore_all().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore_all(FLAC__SeekableStreamDecoder *decoder);
-
-/** Get the current decoder state.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__SeekableStreamDecoderState
- *    The current decoder state.
- */
-FLAC_API FLAC__SeekableStreamDecoderState FLAC__seekable_stream_decoder_get_state(const FLAC__SeekableStreamDecoder *decoder);
-
-/** Get the state of the underlying stream decoder.
- *  Useful when the seekable stream decoder state is
- *  \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    The stream decoder state.
- */
-FLAC_API FLAC__StreamDecoderState FLAC__seekable_stream_decoder_get_stream_decoder_state(const FLAC__SeekableStreamDecoder *decoder);
-
-/** Get the current decoder state as a C string.
- *  This version automatically resolves
- *  \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR by getting the
- *  stream decoder's state.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval const char *
- *    The decoder state as a C string.  Do not modify the contents.
- */
-FLAC_API const char *FLAC__seekable_stream_decoder_get_resolved_state_string(const FLAC__SeekableStreamDecoder *decoder);
-
-/** Get the "MD5 signature checking" flag.
- *  This is the value of the setting, not whether or not the decoder is
- *  currently checking the MD5 (remember, it can be turned off automatically
- *  by a seek).  When the decoder is reset the flag will be restored to the
- *  value returned by this function.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_get_md5_checking(const FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_get_channels().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-FLAC_API unsigned FLAC__seekable_stream_decoder_get_channels(const FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_get_channel_assignment().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__ChannelAssignment
- *    See above.
- */
-FLAC_API FLAC__ChannelAssignment FLAC__seekable_stream_decoder_get_channel_assignment(const FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_get_bits_per_sample().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-FLAC_API unsigned FLAC__seekable_stream_decoder_get_bits_per_sample(const FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_get_sample_rate().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-FLAC_API unsigned FLAC__seekable_stream_decoder_get_sample_rate(const FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_get_blocksize().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-FLAC_API unsigned FLAC__seekable_stream_decoder_get_blocksize(const FLAC__SeekableStreamDecoder *decoder);
-
-/** Returns the decoder's current read position within the stream.
- *  The position is the byte offset from the start of the stream.
- *  Bytes before this position have been fully decoded.  Note that
- *  there may still be undecoded bytes in the decoder's read FIFO.
- *  The returned position is correct even after a seek.
- *
- * \param  decoder   A decoder instance to query.
- * \param  position  Address at which to return the desired position.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code position != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, \c false if there was an error from
- *    the 'tell' callback.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_get_decode_position(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *position);
-
-/** Initialize the decoder instance.
- *  Should be called after FLAC__seekable_stream_decoder_new() and
- *  FLAC__seekable_stream_decoder_set_*() but before any of the
- *  FLAC__seekable_stream_decoder_process_*() functions.  Will set and return
- *  the decoder state, which will be FLAC__SEEKABLE_STREAM_DECODER_OK
- *  if initialization succeeded.
- *
- * \param  decoder  An uninitialized decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__SeekableStreamDecoderState
- *    \c FLAC__SEEKABLE_STREAM_DECODER_OK if initialization was
- *    successful; see FLAC__SeekableStreamDecoderState for the meanings
- *    of other return values.
- */
-FLAC_API FLAC__SeekableStreamDecoderState FLAC__seekable_stream_decoder_init(FLAC__SeekableStreamDecoder *decoder);
-
-/** Finish the decoding process.
- *  Flushes the decoding buffer, releases resources, resets the decoder
- *  settings to their defaults, and returns the decoder state to
- *  FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED.
- *
- *  In the event of a prematurely-terminated decode, it is not strictly
- *  necessary to call this immediately before
- *  FLAC__seekable_stream_decoder_delete() but it is good practice to match
- *  every FLAC__seekable_stream_decoder_init() with a
- *  FLAC__seekable_stream_decoder_finish().
- *
- * \param  decoder  An uninitialized decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if MD5 checking is on AND a STREAMINFO block was available
- *    AND the MD5 signature in the STREAMINFO block was non-zero AND the
- *    signature does not match the one computed by the decoder; else
- *    \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_finish(FLAC__SeekableStreamDecoder *decoder);
-
-/** Flush the stream input.
- *  The decoder's input buffer will be cleared and the state set to
- *  \c FLAC__SEEKABLE_STREAM_DECODER_OK.  This will also turn off MD5
- *  checking.
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false if a memory allocation
- *    or stream decoder error occurs.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_flush(FLAC__SeekableStreamDecoder *decoder);
-
-/** Reset the decoding process.
- *  The decoder's input buffer will be cleared and the state set to
- *  \c FLAC__SEEKABLE_STREAM_DECODER_OK.  This is similar to
- *  FLAC__seekable_stream_decoder_finish() except that the settings are
- *  preserved; there is no need to call FLAC__seekable_stream_decoder_init()
- *  before decoding again.  MD5 checking will be restored to its original
- *  setting.
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false if a memory allocation
- *    or stream decoder error occurs.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_reset(FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_process_single().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_single(FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_process_until_end_of_metadata().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_metadata(FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_process_until_end_of_stream().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_stream(FLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__StreamDecoder; see
- *  FLAC__stream_decoder_skip_single_frame().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_skip_single_frame(FLAC__SeekableStreamDecoder *decoder);
-
-/** Flush the input and seek to an absolute sample.
- *  Decoding will resume at the given sample.  Note that because of
- *  this, the next write callback may contain a partial block.
- *
- * \param  decoder  A decoder instance.
- * \param  sample   The target sample number to seek to.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_seek_absolute(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample);
-
-/* \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/FLAC/seekable_stream_encoder.h b/include/FLAC/seekable_stream_encoder.h
deleted file mode 100644 (file)
index 08ede6e..0000000
+++ /dev/null
@@ -1,1007 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLAC__SEEKABLE_STREAM_ENCODER_H
-#define FLAC__SEEKABLE_STREAM_ENCODER_H
-
-#include "export.h"
-#include "stream_encoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** \file include/FLAC/seekable_stream_encoder.h
- *
- *  \brief
- *  This module contains the functions which implement the seekable stream
- *  encoder.
- *
- *  See the detailed documentation in the
- *  \link flac_seekable_stream_encoder seekable stream encoder \endlink module.
- */
-
-/** \defgroup flac_seekable_stream_encoder FLAC/seekable_stream_encoder.h: seekable stream encoder interface
- *  \ingroup flac_encoder
- *
- *  \brief
- *  This module contains the functions which implement the seekable stream
- *  encoder.
- *
- * The basic usage of this encoder is as follows:
- * - The program creates an instance of an encoder using
- *   FLAC__seekable_stream_encoder_new().
- * - The program overrides the default settings and sets callbacks using
- *   FLAC__seekable_stream_encoder_set_*() functions.
- * - The program initializes the instance to validate the settings and
- *   prepare for encoding using FLAC__seekable_stream_encoder_init().
- * - The program calls FLAC__seekable_stream_encoder_process() or
- *   FLAC__seekable_stream_encoder_process_interleaved() to encode data, which
- *   subsequently calls the callbacks when there is encoder data ready
- *   to be written.
- * - The program finishes the encoding with FLAC__seekable_stream_encoder_finish(),
- *   which causes the encoder to encode any data still in its input pipe,
- *   rewrite the metadata with the final encoding statistics, and finally
- *   reset the encoder to the uninitialized state.
- * - The instance may be used again or deleted with
- *   FLAC__seekable_stream_encoder_delete().
- *
- * The seekable stream encoder is a wrapper around the
- * \link flac_stream_encoder stream encoder \endlink with callbacks for
- * seeking the output and reporting the output stream position.  This
- * allows the encoder to go back and rewrite some of the metadata after
- * encoding if necessary, and provides the metadata callback of the stream
- * encoder internally.  However, you must provide seek and tell callbacks
- * (see FLAC__seekable_stream_encoder_set_seek_callback() and
- * FLAC__seekable_stream_encoder_set_tell_callback()).
- *
- * Make sure to read the detailed description of the
- * \link flac_stream_encoder stream encoder module \endlink since the
- * seekable stream encoder inherits much of its behavior.
- *
- * \note
- * If you are writing the FLAC data to a file, make sure it is open
- * for update (e.g. mode "w+" for stdio streams).  This is because after
- * the first encoding pass, the encoder will try to seek back to the
- * beginning of the stream, to the STREAMINFO block, to write some data
- * there.
- *
- * \note
- * The "set" functions may only be called when the encoder is in the
- * state FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED, i.e. after
- * FLAC__seekable_stream_encoder_new() or FLAC__seekable_stream_encoder_finish(), but
- * before FLAC__seekable_stream_encoder_init().  If this is the case they will
- * return \c true, otherwise \c false.
- *
- * \note
- * FLAC__seekable_stream_encoder_finish() resets all settings to the constructor
- * defaults, including the callbacks.
- *
- * \{
- */
-
-
-/** State values for a FLAC__SeekableStreamEncoder
- *
- *  The encoder's state can be obtained by calling FLAC__seekable_stream_encoder_get_state().
- */
-typedef enum {
-
-       FLAC__SEEKABLE_STREAM_ENCODER_OK = 0,
-       /**< The encoder is in the normal OK state. */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR,
-       /**< An error occurred in the underlying stream encoder;
-        * check FLAC__seekable_stream_encoder_get_stream_encoder_state().
-        */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR,
-       /**< The write callback returned an error. */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR,
-       /**< The read callback returned an error. */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR,
-       /**< The seek callback returned an error. */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR,
-       /**< The tell callback returned an error. */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED,
-       /**< FLAC__seekable_stream_encoder_init() was called when the encoder was
-        * already initialized, usually because
-        * FLAC__seekable_stream_encoder_finish() was not called.
-        */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK,
-       /**< FLAC__seekable_stream_encoder_init() was called without all
-        * callbacks being set.
-        */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE,
-       /**< An invalid seek table was passed is the metadata to
-        * FLAC__seekable_stream_encoder_set_metadata().
-        */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED
-       /**< The encoder is in the uninitialized state. */
-
-} FLAC__SeekableStreamEncoderState;
-
-/** Maps a FLAC__SeekableStreamEncoderState to a C string.
- *
- *  Using a FLAC__SeekableStreamEncoderState as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__SeekableStreamEncoderStateString[];
-
-
-/** Return values for the FLAC__SeekableStreamEncoder seek callback.
- */
-typedef enum {
-
-       FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK,
-       /**< The seek was OK and encoding can continue. */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR
-       /**< An unrecoverable error occurred.  The encoder will return from the process call. */
-
-} FLAC__SeekableStreamEncoderSeekStatus;
-
-/** Maps a FLAC__SeekableStreamEncoderSeekStatus to a C string.
- *
- *  Using a FLAC__SeekableStreamEncoderSeekStatus as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__SeekableStreamEncoderSeekStatusString[];
-
-
-/** Return values for the FLAC__SeekableStreamEncoder tell callback.
- */
-typedef enum {
-
-       FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK,
-       /**< The tell was OK and encoding can continue. */
-
-       FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_ERROR
-       /**< An unrecoverable error occurred.  The encoder will return from the process call. */
-
-} FLAC__SeekableStreamEncoderTellStatus;
-
-/** Maps a FLAC__SeekableStreamEncoderTellStatus to a C string.
- *
- *  Using a FLAC__SeekableStreamEncoderTellStatus as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern FLAC_API const char * const FLAC__SeekableStreamEncoderTellStatusString[];
-
-
-/***********************************************************************
- *
- * class FLAC__SeekableStreamEncoder
- *
- ***********************************************************************/
-
-struct FLAC__SeekableStreamEncoderProtected;
-struct FLAC__SeekableStreamEncoderPrivate;
-/** The opaque structure definition for the seekable stream encoder type.
- *  See the \link flac_seekable_stream_encoder seekable stream encoder module \endlink
- *  for a detailed description.
- */
-typedef struct {
-       struct FLAC__SeekableStreamEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */
-       struct FLAC__SeekableStreamEncoderPrivate *private_; /* avoid the C++ keyword 'private' */
-} FLAC__SeekableStreamEncoder;
-
-/** Signature for the seek callback.
- *  See FLAC__seekable_stream_encoder_set_seek_callback() for more info.
- *
- * \param  encoder  The encoder instance calling the callback.
- * \param  absolute_byte_offset  The offset from the beginning of the stream
- *                               to seek to.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_encoder_set_client_data().
- * \retval FLAC__SeekableStreamEncoderSeekStatus
- *    The callee's return status.
- */
-typedef FLAC__SeekableStreamEncoderSeekStatus (*FLAC__SeekableStreamEncoderSeekCallback)(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-
-/** Signature for the tell callback.
- *  See FLAC__seekable_stream_encoder_set_tell_callback() for more info.
- *
- * \warning
- * The callback must return the true current byte offset of the output to
- * which the encoder is writing.  If you are buffering the output, make
- * sure and take this into account.  If you are writing directly to a
- * FILE* from your write callback, ftell() is sufficient.  If you are
- * writing directly to a file descriptor from your write callback, you
- * can use lseek(fd, SEEK_CUR, 0).  The encoder may later seek back to
- * these points to rewrite metadata after encoding.
- *
- * \param  encoder  The encoder instance calling the callback.
- * \param  absolute_byte_offset  The address at which to store the current
- *                               position of the output.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_encoder_set_client_data().
- * \retval FLAC__SeekableStreamEncoderTellStatus
- *    The callee's return status.
- */
-typedef FLAC__SeekableStreamEncoderTellStatus (*FLAC__SeekableStreamEncoderTellCallback)(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-
-/** Signature for the write callback.
- *  See FLAC__seekable_stream_encoder_set_write_callback()
- *  and FLAC__StreamEncoderWriteCallback for more info.
- *
- * \param  encoder  The encoder instance calling the callback.
- * \param  buffer   An array of encoded data of length \a bytes.
- * \param  bytes    The byte length of \a buffer.
- * \param  samples  The number of samples encoded by \a buffer.
- *                  \c 0 has a special meaning; see
- *                  FLAC__stream_encoder_set_write_callback().
- * \param  current_frame  The number of current frame being encoded.
- * \param  client_data  The callee's client data set through
- *                      FLAC__seekable_stream_encoder_set_client_data().
- * \retval FLAC__StreamEncoderWriteStatus
- *    The callee's return status.
- */
-typedef FLAC__StreamEncoderWriteStatus (*FLAC__SeekableStreamEncoderWriteCallback)(const FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-/** Create a new seekable stream encoder instance.  The instance is created with
- *  default settings; see the individual FLAC__seekable_stream_encoder_set_*()
- *  functions for each setting's default.
- *
- * \retval FLAC__SeekableStreamEncoder*
- *    \c NULL if there was an error allocating memory, else the new instance.
- */
-FLAC_API FLAC__SeekableStreamEncoder *FLAC__seekable_stream_encoder_new();
-
-/** Free an encoder instance.  Deletes the object pointed to by \a encoder.
- *
- * \param encoder  A pointer to an existing encoder.
- * \assert
- *    \code encoder != NULL \endcode
- */
-FLAC_API void FLAC__seekable_stream_encoder_delete(FLAC__SeekableStreamEncoder *encoder);
-
-/***********************************************************************
- *
- * Public class method prototypes
- *
- ***********************************************************************/
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_verify().
- *
- * \default \c true
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_verify(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_streamable_subset().
- *
- * \default \c true
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_streamable_subset(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_do_mid_side_stereo().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_do_mid_side_stereo(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_loose_mid_side_stereo().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_channels().
- *
- * \default \c 2
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_channels(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_bits_per_sample().
- *
- * \warning
- * Do not feed the encoder data that is wider than the value you
- * set here or you will generate an invalid stream.
- *
- * \default \c 16
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_bits_per_sample(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_sample_rate().
- *
- * \default \c 44100
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_sample_rate(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_blocksize().
- *
- * \default \c 1152
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_blocksize(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_apodization().
- *
- * \default \c 0
- * \param  encoder        An encoder instance to set.
- * \param  specification  See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code specification != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-/* @@@@add to unit tests*/
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_apodization(FLAC__SeekableStreamEncoder *encoder, const char *specification);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_max_lpc_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_max_lpc_order(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_qlp_coeff_precision().
- *
- * \note
- * In the current implementation, qlp_coeff_precision + bits_per_sample must
- * be less than 32.
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_qlp_coeff_precision(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_do_qlp_coeff_prec_search().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_do_escape_coding().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_do_escape_coding(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_do_exhaustive_model_search().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_min_residual_partition_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_min_residual_partition_order(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_max_residual_partition_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_max_residual_partition_order(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_rice_parameter_search_dist().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_rice_parameter_search_dist(FLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_total_samples_estimate().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_total_samples_estimate(FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 value);
-
-/** This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_metadata().
- *
- * \note
- * SEEKTABLE blocks are handled specially.  Since you will not know
- * the values for the seek point stream offsets, you should pass in
- * a SEEKTABLE 'template', that is, a SEEKTABLE object with the
- * required sample numbers (or placeholder points), with \c 0 for the
- * \a frame_samples and \a stream_offset fields for each point.  While
- * encoding, the encoder will fill them in for you and when encoding
- * is finished, it will seek back and write the real values into the
- * SEEKTABLE block in the stream.  There are helper routines for
- * manipulating seektable template blocks; see metadata.h:
- * FLAC__metadata_object_seektable_template_*().
- *
- * \note
- * The encoder instance \b will modify the first \c SEEKTABLE block
- * as it transforms the template to a valid seektable while encoding,
- * but it is still up to the caller to free all metadata blocks after
- * encoding.
- *
- * \default \c NULL, 0
- * \param  encoder     An encoder instance to set.
- * \param  metadata    See above.
- * \param  num_blocks  See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_metadata(FLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
-
-/** Set the seek callback.
- *  The supplied function will be called when the encoder needs to seek
- *  the output stream.  The encoder will pass the absolute byte offset
- *  to seek to, 0 meaning the beginning of the stream.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_seek_callback(FLAC__SeekableStreamEncoder *encoder, FLAC__SeekableStreamEncoderSeekCallback value);
-
-/** Set the tell callback.
- *  The supplied function will be called when the encoder needs to know
- *  the current position of the output stream.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_tell_callback(FLAC__SeekableStreamEncoder *encoder, FLAC__SeekableStreamEncoderTellCallback value);
-
-/** Set the write callback.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_write_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_write_callback(FLAC__SeekableStreamEncoder *encoder, FLAC__SeekableStreamEncoderWriteCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_client_data(FLAC__SeekableStreamEncoder *encoder, void *value);
-
-/** Get the current encoder state.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__SeekableStreamEncoderState
- *    The current encoder state.
- */
-FLAC_API FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_get_state(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the state of the underlying stream encoder.
- *  Useful when the seekable stream encoder state is
- *  \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__StreamEncoderState
- *    The stream encoder state.
- */
-FLAC_API FLAC__StreamEncoderState FLAC__seekable_stream_encoder_get_stream_encoder_state(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the state of the underlying stream encoder's verify decoder.
- *  Useful when the seekable stream encoder state is
- *  \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR and the
- *  stream encoder state is \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    The stream encoder state.
- */
-FLAC_API FLAC__StreamDecoderState FLAC__seekable_stream_encoder_get_verify_decoder_state(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the current encoder state as a C string.
- *  This version automatically resolves
- *  \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR by getting the
- *  stream encoder's state.
- *
- * \param  encoder  A encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval const char *
- *    The encoder state as a C string.  Do not modify the contents.
- */
-FLAC_API const char *FLAC__seekable_stream_encoder_get_resolved_state_string(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get relevant values about the nature of a verify decoder error.
- *  Inherited from FLAC__stream_encoder_get_verify_decoder_error_stats().
- *  Useful when the seekable stream encoder state is
- *  \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR and the
- *  stream encoder state is
- *  \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \param  absolute_sample  The absolute sample number of the mismatch.
- * \param  frame_number  The number of the frame in which the mismatch occurred.
- * \param  channel       The channel in which the mismatch occurred.
- * \param  sample        The number of the sample (relative to the frame) in
- *                       which the mismatch occurred.
- * \param  expected      The expected value for the sample in question.
- * \param  got           The actual value returned by the decoder.
- * \assert
- *    \code encoder != NULL \endcode
- */
-FLAC_API void FLAC__seekable_stream_encoder_get_verify_decoder_error_stats(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-
-/** Get the "verify" flag.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_verify().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__seekable_stream_encoder_set_verify().
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_verify(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the "streamable subset" flag.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_streamable_subset().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__seekable_stream_encoder_set_streamable_subset().
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_streamable_subset(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the "mid/side stereo coding" flag.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_do_mid_side_stereo().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__seekable_stream_encoder_get_do_mid_side_stereo().
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_do_mid_side_stereo(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the "adaptive mid/side switching" flag.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_loose_mid_side_stereo().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__seekable_stream_encoder_set_loose_mid_side_stereo().
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_loose_mid_side_stereo(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the number of input channels being processed.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_channels().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_channels().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_channels(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the input sample resolution setting.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_bits_per_sample().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_bits_per_sample().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_bits_per_sample(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the input sample rate setting.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_sample_rate().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_sample_rate().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_sample_rate(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the blocksize setting.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_blocksize().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_blocksize().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_blocksize(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the maximum LPC order setting.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_max_lpc_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_max_lpc_order().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_max_lpc_order(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the quantized linear predictor coefficient precision setting.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_qlp_coeff_precision().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_qlp_coeff_precision().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_qlp_coeff_precision(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the qlp coefficient precision search flag.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_do_qlp_coeff_prec_search().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search().
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the "escape coding" flag.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_do_escape_coding().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__seekable_stream_encoder_set_do_escape_coding().
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_do_escape_coding(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the exhaustive model search flag.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_do_exhaustive_model_search().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See FLAC__seekable_stream_encoder_set_do_exhaustive_model_search().
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_do_exhaustive_model_search(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the minimum residual partition order setting.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_min_residual_partition_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_min_residual_partition_order().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_min_residual_partition_order(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get maximum residual partition order setting.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_max_residual_partition_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_max_residual_partition_order().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_max_residual_partition_order(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the Rice parameter search distance setting.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_rice_parameter_search_dist().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__seekable_stream_encoder_set_rice_parameter_search_dist().
- */
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Get the previously set estimate of the total samples to be encoded.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_get_total_samples_estimate().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__uint64
- *    See FLAC__seekable_stream_encoder_set_total_samples_estimate().
- */
-FLAC_API FLAC__uint64 FLAC__seekable_stream_encoder_get_total_samples_estimate(const FLAC__SeekableStreamEncoder *encoder);
-
-/** Initialize the encoder instance.
- *  Should be called after FLAC__seekable_stream_encoder_new() and
- *  FLAC__seekable_stream_encoder_set_*() but before FLAC__seekable_stream_encoder_process()
- *  or FLAC__seekable_stream_encoder_process_interleaved().  Will set and return
- *  the encoder state, which will be FLAC__SEEKABLE_STREAM_ENCODER_OK if
- *  initialization succeeded.
- *
- *  The call to FLAC__seekable_stream_encoder_init() currently will also immediately
- *  call the write callback with the \c fLaC signature and all the encoded
- *  metadata.
- *
- * \param  encoder  An uninitialized encoder instance.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__SeekableStreamEncoderState
- *    \c FLAC__SEEKABLE_STREAM_ENCODER_OK if initialization was successful; see
- *    FLAC__SeekableStreamEncoderState for the meanings of other return values.
- */
-FLAC_API FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_init(FLAC__SeekableStreamEncoder *encoder);
-
-/** Finish the encoding process.
- *  Flushes the encoding buffer, releases resources, resets the encoder
- *  settings to their defaults, and returns the encoder state to
- *  FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED.
- *
- *  In the event of a prematurely-terminated encode, it is not strictly
- *  necessary to call this immediately before FLAC__seekable_stream_encoder_delete()
- *  but it is good practice to match every FLAC__seekable_stream_encoder_init()
- *  with a FLAC__seekable_stream_encoder_finish().
- *
- * \param  encoder  An uninitialized encoder instance.
- * \assert
- *    \code encoder != NULL \endcode
- */
-FLAC_API void FLAC__seekable_stream_encoder_finish(FLAC__SeekableStreamEncoder *encoder);
-
-/** Submit data for encoding.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_process().
- *
- * \param  encoder  An initialized encoder instance in the OK state.
- * \param  buffer   An array of pointers to each channel's signal.
- * \param  samples  The number of samples in one channel.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code FLAC__seekable_stream_encoder_get_state(encoder) == FLAC__SEEKABLE_STREAM_ENCODER_OK \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false; in this case, check the
- *    encoder state with FLAC__seekable_stream_encoder_get_state() to see what
- *    went wrong.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_process(FLAC__SeekableStreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples);
-
-/** Submit data for encoding.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_process_interleaved().
- *
- * \param  encoder  An initialized encoder instance in the OK state.
- * \param  buffer   An array of channel-interleaved data (see above).
- * \param  samples  The number of samples in one channel, the same as for
- *                  FLAC__seekable_stream_encoder_process().  For example, if
- *                  encoding two channels, \c 1000 \a samples corresponds
- *                  to a \a buffer of 2000 values.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code FLAC__seekable_stream_encoder_get_state(encoder) == FLAC__SEEKABLE_STREAM_ENCODER_OK \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false; in this case, check the
- *    encoder state with FLAC__seekable_stream_encoder_get_state() to see what
- *    went wrong.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_process_interleaved(FLAC__SeekableStreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples);
-
-/* \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
index fb12acc..95947af 100644 (file)
@@ -32,6 +32,7 @@
 #ifndef FLAC__STREAM_DECODER_H
 #define FLAC__STREAM_DECODER_H
 
+#include <stdio.h> /* for FILE */
 #include "export.h"
 #include "format.h"
 
@@ -54,24 +55,22 @@ extern "C" {
  *  \ingroup flac
  *
  *  \brief
- *  This module describes the three decoder layers provided by libFLAC.
- *
- * For decoding FLAC streams, libFLAC provides three layers of access.  The
- * lowest layer is non-seekable stream-level decoding, the next is seekable
- * stream-level decoding, and the highest layer is file-level decoding.  The
- * interfaces are described in the \link flac_stream_decoder stream decoder
- * \endlink, \link flac_seekable_stream_decoder seekable stream decoder
- * \endlink, and \link flac_file_decoder file decoder \endlink modules
- * respectively.  Typically you will choose the highest layer that your input
- * source will support.
- *
- * The stream decoder relies on callbacks for all input and output and has no
- * provisions for seeking.  The seekable stream decoder wraps the stream
- * decoder and exposes functions for seeking.  However, you must provide
- * extra callbacks for seek-related operations on your stream, like seek and
- * tell.  The file decoder wraps the seekable stream decoder and supplies
- * most of the callbacks internally, simplifying the processing of standard
- * files.
+ *  This module describes the two decoder layers provided by libFLAC.
+ *
+ * libFLAC provides two ways of decoding FLAC streams.  There is a @@@@@@frame decoder which decodes single frames at a time, and a stream decoder which decodes whole streams.
+ *
+ * @@@@@@TODO frame decoder
+ *
+ * The stream decoder can be used decode complete streams either from the
+ * client via callbacks, or directly from a file, depending on how it is
+ * initialized.  When decoding via callbacks, the client provides
+ * callbacks for reading FLAC data and writing decoded samples, and
+ * handling metadata and errors.  If the client also supplies seek-related
+ * callback, the decoder function for sample-accurate seeking within the
+ * FLAC input is also available.  When decoding from a file, the client
+ * needs only supply a filename or open \c FILE* and write/metadata/error
+ * callbacks; the rest of the callbacks are supplied internally.  For more
+ * info see the \link flac_stream_decoder stream decoder \endlink module.
  */
 
 /** \defgroup flac_stream_decoder FLAC/stream_decoder.h: stream decoder interface
@@ -84,11 +83,12 @@ extern "C" {
  * The basic usage of this decoder is as follows:
  * - The program creates an instance of a decoder using
  *   FLAC__stream_decoder_new().
- * - The program overrides the default settings and sets callbacks for
- *   reading, writing, error reporting, and metadata reporting using
+ * - The program overrides the default settings using
  *   FLAC__stream_decoder_set_*() functions.
  * - The program initializes the instance to validate the settings and
- *   prepare for decoding using FLAC__stream_decoder_init().
+ *   prepare for decoding using FLAC__stream_decoder_init() or
+ *   FLAC__stream_decoder_init_FILE() or FLAC__stream_decoder_init_file(),
+ *   depending on the nature of the input.
  * - The program calls the FLAC__stream_decoder_process_*() functions
  *   to decode data, which subsequently calls the callbacks.
  * - The program finishes the decoding with FLAC__stream_decoder_finish(),
@@ -99,33 +99,21 @@ extern "C" {
  *
  * In more detail, the program will create a new instance by calling
  * FLAC__stream_decoder_new(), then call FLAC__stream_decoder_set_*()
- * functions to set the callbacks and client data, and call
- * FLAC__stream_decoder_init().  The required callbacks are:
- *
- * - Read callback - This function will be called when the decoder needs
- *   more input data.  The address of the buffer to be filled is supplied,
- *   along with the number of bytes the buffer can hold.  The callback may
- *   choose to supply less data and modify the byte count but must be careful
- *   not to overflow the buffer.  The callback then returns a status code
- *   chosen from FLAC__StreamDecoderReadStatus.
- * - Write callback - This function will be called when the decoder has
- *   decoded a single frame of data.  The decoder will pass the frame
- *   metadata as well as an array of pointers (one for each channel)
- *   pointing to the decoded audio.
- * - Metadata callback - This function will be called when the decoder has
- *   decoded a metadata block.  In a valid FLAC file there will always be
- *   one STREAMINFO block, followed by zero or more other metadata
- *   blocks.  These will be supplied by the decoder in the same order as
- *   they appear in the stream and always before the first audio frame
- *   (i.e. write callback).  The metadata block that is passed in must not
- *   be modified, and it doesn't live beyond the callback, so you should
- *   make a copy of it with FLAC__metadata_object_clone() if you will need
- *   it elsewhere.  Since metadata blocks can potentially be large, by
- *   default the decoder only calls the metadata callback for the STREAMINFO
- *   block; you can instruct the decoder to pass or filter other blocks with
- *   FLAC__stream_decoder_set_metadata_*() calls.
- * - Error callback - This function will be called whenever an error occurs
- *   during decoding.
+ * functions to override the default decoder options, and call
+ * on of the FLAC__stream_decoder_init_*() functions.
+ *
+ * There are three initialization functions, one for setting up the decoder
+ * to decode FLAC data from the client via callbacks, and two for decoding
+ * directly from a FLAC file.
+ *
+ * For decoding via callbacks, use FLAC__stream_decoder_init_stream().
+ * You must also supply several callbacks for handling I/O.  Some (like
+ * seeking) are optional, depending on the capabilities of the input.
+ *
+ * For decoding directly from a file, use FLAC__stream_decoder_init_FILE()
+ * or FLAC__stream_decoder_init_file().  Then you must only supply a
+ * filename or open \c FILE* and fewer callbacks; the decoder will handle
+ * the other callbacks internally.
  *
  * Once the decoder is initialized, your program will call one of several
  * functions to start the decoding process:
@@ -151,11 +139,23 @@ extern "C" {
  * instance may be deleted with FLAC__stream_decoder_delete() or initialized
  * again to decode another stream.
  *
- * Note that the stream decoder has no real concept of stream position, it
- * just converts data.  To seek within a stream the callbacks have only to
- * flush the decoder using FLAC__stream_decoder_flush() and start feeding
- * data from the new position through the read callback.  The seekable
- * stream decoder does just this.
+ * Seeking is exposed through the FLAC__stream_decoder_seek_absolute() method.
+ * At any point after the stream decoder has been initialized, the user can
+ * call this function to seek to an exact sample within the stream.
+ * Subsequently, the first time the write callback is called it will be
+ * passed a (possibly partial) block starting at that sample.
+ *
+ * If the client cannot seek via the callback interface provided, but still
+ * has another way of seeking, it can flush the decoder using
+ * FLAC__stream_decoder_flush() and start feeding data from the new position
+ * through the read callback.
+ *
+ * The stream decoder also provides MD5 signature checking.  If this is
+ * turned on before initialization, FLAC__stream_decoder_finish() will
+ * report when the decoded MD5 signature does not match the one stored
+ * in the STREAMINFO block.  MD5 checking is automatically turned off
+ * (until the next FLAC__stream_decoder_reset()) if there is no signature
+ * in the STREAMINFO block or when a seek is attempted.
  *
  * The FLAC__stream_decoder_set_metadata_*() functions deserve special
  * attention.  By default, the decoder only calls the metadata_callback for
@@ -191,7 +191,7 @@ extern "C" {
 
 /** State values for a FLAC__StreamDecoder
  *
- *  The decoder's state can be obtained by calling FLAC__stream_decoder_get_state().
+ * The decoder's state can be obtained by calling FLAC__stream_decoder_get_state().
  */
 typedef enum {
 
@@ -202,7 +202,9 @@ typedef enum {
        /**< The decoder is ready to or is in the process of reading metadata. */
 
        FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC,
-       /**< The decoder is ready to or is in the process of searching for the frame sync code. */
+       /**< The decoder is ready to or is in the process of searching for the
+        * frame sync code.
+        */
 
        FLAC__STREAM_DECODER_READ_FRAME,
        /**< The decoder is ready to or is in the process of reading a frame. */
@@ -210,23 +212,25 @@ typedef enum {
        FLAC__STREAM_DECODER_END_OF_STREAM,
        /**< The decoder has reached the end of the stream. */
 
+       FLAC__STREAM_DECODER_SEEK_ERROR,
+       /**< An error occurred while seeking.  The decoder must be flushed
+        * with FLAC__stream_decoder_flush() or reset with
+        * FLAC__stream_decoder_reset() before decoding can continue.
+        */
+
        FLAC__STREAM_DECODER_ABORTED,
        /**< The decoder was aborted by the read callback. */
 
        FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
-       /**< An error occurred allocating memory. */
-
-       FLAC__STREAM_DECODER_ALREADY_INITIALIZED,
-       /**< FLAC__stream_decoder_init() was called when the decoder was
-        * already initialized, usually because
-        * FLAC__stream_decoder_finish() was not called.
+       /**< An error occurred allocating memory.  The decoder is in an invalid
+        * state and can no longer be used.
         */
 
-       FLAC__STREAM_DECODER_INVALID_CALLBACK,
-       /**< FLAC__stream_decoder_init() was called without all callbacks being set. */
-
        FLAC__STREAM_DECODER_UNINITIALIZED
-       /**< The decoder is in the uninitialized state. */
+       /**< The decoder is in the uninitialized state; one of the
+        * FLAC__stream_decoder_init_*() functions must be called before samples
+        * can be processed.
+        */
 
 } FLAC__StreamDecoderState;
 
@@ -238,6 +242,38 @@ typedef enum {
 extern FLAC_API const char * const FLAC__StreamDecoderStateString[];
 
 
+/** Possible return values for the FLAC__stream_decoder_init_*() functions.
+ */
+typedef enum {
+
+       FLAC__STREAM_DECODER_INIT_STATUS_OK = 0,
+       /**< Initialization was successful. */
+
+       FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS,
+       /**< A required callback was not supplied. */
+
+       FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR,
+       /**< An error occurred allocating memory. */
+
+       FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE,
+       /**< fopen() failed in FLAC__stream_decoder_init_file(). */
+
+       FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED
+       /**< FLAC__stream_decoder_init_*() was called when the decoder was
+        * already initialized, usually because
+        * FLAC__stream_decoder_finish() was not called.
+        */
+
+} FLAC__StreamDecoderInitStatus;
+
+/** Maps a FLAC__StreamDecoderInitStatus to a C string.
+ *
+ *  Using a FLAC__StreamDecoderInitStatus as the index to this array
+ *  will give the string equivalent.  The contents should not be modified.
+ */
+extern FLAC_API const char * const FLAC__StreamDecoderInitStatusString[];
+
+
 /** Return values for the FLAC__StreamDecoder read callback.
  */
 typedef enum {
@@ -246,7 +282,15 @@ typedef enum {
        /**< The read was OK and decoding can continue. */
 
        FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM,
-       /**< The read was attempted at the end of the stream. */
+       /**< The read was attempted while at the end of the stream.  Note that
+        * the client must only return this value when the read callback was
+        * called when already at the end of the stream.  Otherwise, if the read
+        * itself moves to the end of the stream, the client should still return
+        * the data and \c FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, and then on
+        * the next read callback it should return
+        * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM with a byte count
+        * of \c 0.
+        */
 
        FLAC__STREAM_DECODER_READ_STATUS_ABORT
        /**< An unrecoverable error occurred.  The decoder will return from the process call. */
@@ -261,6 +305,75 @@ typedef enum {
 extern FLAC_API const char * const FLAC__StreamDecoderReadStatusString[];
 
 
+/** Return values for the FLAC__StreamDecoder seek callback.
+ */
+typedef enum {
+
+       FLAC__STREAM_DECODER_SEEK_STATUS_OK,
+       /**< The seek was OK and decoding can continue. */
+
+       FLAC__STREAM_DECODER_SEEK_STATUS_ERROR,
+       /**< An unrecoverable error occurred.  The decoder will return from the process call. */
+
+       FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED
+       /**< Client does not support seeking. */
+
+} FLAC__StreamDecoderSeekStatus;
+
+/** Maps a FLAC__StreamDecoderSeekStatus to a C string.
+ *
+ *  Using a FLAC__StreamDecoderSeekStatus as the index to this array
+ *  will give the string equivalent.  The contents should not be modified.
+ */
+extern FLAC_API const char * const FLAC__StreamDecoderSeekStatusString[];
+
+
+/** Return values for the FLAC__StreamDecoder tell callback.
+ */
+typedef enum {
+
+       FLAC__STREAM_DECODER_TELL_STATUS_OK,
+       /**< The tell was OK and decoding can continue. */
+
+       FLAC__STREAM_DECODER_TELL_STATUS_ERROR,
+       /**< An unrecoverable error occurred.  The decoder will return from the process call. */
+
+       FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED
+       /**< Client does not support telling the position. */
+
+} FLAC__StreamDecoderTellStatus;
+
+/** Maps a FLAC__StreamDecoderTellStatus to a C string.
+ *
+ *  Using a FLAC__StreamDecoderTellStatus as the index to this array
+ *  will give the string equivalent.  The contents should not be modified.
+ */
+extern FLAC_API const char * const FLAC__StreamDecoderTellStatusString[];
+
+
+/** Return values for the FLAC__StreamDecoder length callback.
+ */
+typedef enum {
+
+       FLAC__STREAM_DECODER_LENGTH_STATUS_OK,
+       /**< The length call was OK and decoding can continue. */
+
+       FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR,
+       /**< An unrecoverable error occurred.  The decoder will return from the process call. */
+
+       FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
+       /**< Client does not support reporting the length. */
+
+} FLAC__StreamDecoderLengthStatus;
+
+/** Maps a FLAC__StreamDecoderLengthStatus to a C string.
+ *
+ *  Using a FLAC__StreamDecoderLengthStatus as the index to this array
+ *  will give the string equivalent.  The contents should not be modified.
+ */
+extern FLAC_API const char * const FLAC__StreamDecoderLengthStatusString[];
+
+
 /** Return values for the FLAC__StreamDecoder write callback.
  */
 typedef enum {
@@ -338,7 +451,18 @@ typedef struct {
 } FLAC__StreamDecoder;
 
 /** Signature for the read callback.
- *  See FLAC__stream_decoder_set_read_callback() for more info.
+ *
+ *  A function pointer matching this signature must be passed to
+ *  FLAC__stream_decoder_init_stream(). The supplied function will be
+ *  called when the decoder needs more input data.  The address of the
+ *  buffer to be filled is supplied, along with the number of bytes the
+ *  buffer can hold.  The callback may choose to supply less data and
+ *  modify the byte count but must be careful not to overflow the buffer.
+ *  The callback then returns a status code chosen from
+ *  FLAC__StreamDecoderReadStatus.
+ *
+ * \note In general, FLAC__StreamDecoder functions which change the
+ * state should not be called on the \a decoder while in the callback.
  *
  * \param  decoder  The decoder instance calling the callback.
  * \param  buffer   A pointer to a location for the callee to store
@@ -350,14 +474,103 @@ typedef struct {
  *                  stored (0 in case of error or end-of-stream) before
  *                  returning.
  * \param  client_data  The callee's client data set through
- *                      FLAC__stream_decoder_set_client_data().
+ *                      FLAC__stream_decoder_init_*().
  * \retval FLAC__StreamDecoderReadStatus
  *    The callee's return status.
  */
 typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
 
+/** Signature for the seek callback.
+ *
+ *  A function pointer matching this signature may be passed to
+ *  FLAC__stream_decoder_init_stream().  The supplied function will be
+ *  called when the decoder needs to seek the input stream.  The decoder
+ *  will pass the absolute byte offset to seek to, 0 meaning the
+ *  beginning of the stream.
+ *
+ * \note In general, FLAC__StreamDecoder functions which change the
+ * state should not be called on the \a decoder while in the callback.
+ *
+ * \param  decoder  The decoder instance calling the callback.
+ * \param  absolute_byte_offset  The offset from the beginning of the stream
+ *                               to seek to.
+ * \param  client_data  The callee's client data set through
+ *                      FLAC__stream_decoder_init_*().
+ * \retval FLAC__StreamDecoderSeekStatus
+ *    The callee's return status.
+ */
+typedef FLAC__StreamDecoderSeekStatus (*FLAC__StreamDecoderSeekCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+
+/** Signature for the tell callback.
+ *
+ *  A function pointer matching this signature may be passed to
+ *  FLAC__stream_decoder_init_stream().  The supplied function will be
+ *  called when the decoder wants to know the current position of the
+ *  stream.  The callback should return the byte offset from the
+ *  beginning of the stream.
+ *
+ * \note In general, FLAC__StreamDecoder functions which change the
+ * state should not be called on the \a decoder while in the callback.
+ *
+ * \param  decoder  The decoder instance calling the callback.
+ * \param  absolute_byte_offset  A pointer to storage for the current offset
+ *                               from the beginning of the stream.
+ * \param  client_data  The callee's client data set through
+ *                      FLAC__stream_decoder_init_*().
+ * \retval FLAC__StreamDecoderTellStatus
+ *    The callee's return status.
+ */
+typedef FLAC__StreamDecoderTellStatus (*FLAC__StreamDecoderTellCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+
+/** Signature for the length callback.
+ *
+ *  A function pointer matching this signature may be passed to
+ *  FLAC__stream_decoder_init_stream().  The supplied function will be
+ *  called when the decoder wants to know the total length of the stream
+ *  in bytes.
+ *
+ * \note In general, FLAC__StreamDecoder functions which change the
+ * state should not be called on the \a decoder while in the callback.
+ *
+ * \param  decoder  The decoder instance calling the callback.
+ * \param  stream_length  A pointer to storage for the length of the stream
+ *                        in bytes.
+ * \param  client_data  The callee's client data set through
+ *                      FLAC__stream_decoder_init_*().
+ * \retval FLAC__StreamDecoderLengthStatus
+ *    The callee's return status.
+ */
+typedef FLAC__StreamDecoderLengthStatus (*FLAC__StreamDecoderLengthCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
+
+/** Signature for the EOF callback.
+ *
+ *  A function pointer matching this signature may be passed to
+ *  FLAC__stream_decoder_init_stream().  The supplied function will be
+ *  called when the decoder needs to know if the end of the stream has
+ *  been reached.
+ *
+ * \note In general, FLAC__StreamDecoder functions which change the
+ * state should not be called on the \a decoder while in the callback.
+ *
+ * \param  decoder  The decoder instance calling the callback.
+ * \param  client_data  The callee's client data set through
+ *                      FLAC__stream_decoder_init_*().
+ * \retval FLAC__bool
+ *    \c true if the currently at the end of the stream, else \c false.
+ */
+typedef FLAC__bool (*FLAC__StreamDecoderEofCallback)(const FLAC__StreamDecoder *decoder, void *client_data);
+
 /** Signature for the write callback.
- *  See FLAC__stream_decoder_set_write_callback() for more info.
+ *
+ *  A function pointer matching this signature must be passed to one of
+ *  the FLAC__stream_decoder_init_*() functions.
+ *  The supplied function will be called when the decoder has decoded a
+ *  single audio frame.  The decoder will pass the frame metadata as well
+ *  as an array of pointers (one for each channel) pointing to the
+ *  decoded audio.
+ *
+ * \note In general, FLAC__StreamDecoder functions which change the
+ * state should not be called on the \a decoder while in the callback.
  *
  * \param  decoder  The decoder instance calling the callback.
  * \param  frame    The description of the decoded frame.  See
@@ -369,29 +582,53 @@ typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const F
  *                  except for stereo streams; in this case channel
  *                  0 is left and 1 is right.
  * \param  client_data  The callee's client data set through
- *                      FLAC__stream_decoder_set_client_data().
+ *                      FLAC__stream_decoder_init_*().
  * \retval FLAC__StreamDecoderWriteStatus
  *    The callee's return status.
  */
 typedef FLAC__StreamDecoderWriteStatus (*FLAC__StreamDecoderWriteCallback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
 
 /** Signature for the metadata callback.
- *  See FLAC__stream_decoder_set_metadata_callback() for more info.
+ *
+ *  A function pointer matching this signature must be passed to one of
+ *  the FLAC__stream_decoder_init_*() functions.
+ *  The supplied function will be called when the decoder has decoded a
+ *  metadata block.  In a valid FLAC file there will always be one
+ *  \c STREAMINFO block, followed by zero or more other metadata blocks.
+ *  These will be supplied by the decoder in the same order as they
+ *  appear in the stream and always before the first audio frame (i.e.
+ *  write callback).  The metadata block that is passed in must not be
+ *  modified, and it doesn't live beyond the callback, so you should make
+ *  a copy of it with FLAC__metadata_object_clone() if you will need it
+ *  elsewhere.  Since metadata blocks can potentially be large, by
+ *  default the decoder only calls the metadata callback for the
+ *  \c STREAMINFO block; you can instruct the decoder to pass or filter
+ *  other blocks with FLAC__stream_decoder_set_metadata_*() calls.
+ *
+ * \note In general, FLAC__StreamDecoder functions which change the
+ * state should not be called on the \a decoder while in the callback.
  *
  * \param  decoder  The decoder instance calling the callback.
  * \param  metadata The decoded metadata block.
  * \param  client_data  The callee's client data set through
- *                      FLAC__stream_decoder_set_client_data().
+ *                      FLAC__stream_decoder_init_*().
  */
 typedef void (*FLAC__StreamDecoderMetadataCallback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
 
 /** Signature for the error callback.
- *  See FLAC__stream_decoder_set_error_callback() for more info.
+ *
+ *  A function pointer matching this signature must be passed to one of
+ *  the FLAC__stream_decoder_init_*() functions.
+ *  The supplied function will be called whenever an error occurs during
+ *  decoding.
+ *
+ * \note In general, FLAC__StreamDecoder functions which change the
+ * state should not be called on the \a decoder while in the callback.
  *
  * \param  decoder  The decoder instance calling the callback.
  * \param  status   The error encountered by the decoder.
  * \param  client_data  The callee's client data set through
- *                      FLAC__stream_decoder_set_client_data().
+ *                      FLAC__stream_decoder_init_*().
  */
 typedef void (*FLAC__StreamDecoderErrorCallback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
 
@@ -426,107 +663,27 @@ FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder);
  *
  ***********************************************************************/
 
-/** Set the read callback.
- *  The supplied function will be called when the decoder needs more input
- *  data.  The address of the buffer to be filled is supplied, along with
- *  the number of bytes the buffer can hold.  The callback may choose to
- *  supply less data and modify the byte count but must be careful not to
- *  overflow the buffer.  The callback then returns a status code chosen
- *  from FLAC__StreamDecoderReadStatus.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__stream_decoder_set_read_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback value);
-
-/** Set the write callback.
- *  The supplied function will be called when the decoder has decoded a
- *  single frame of data.  The decoder will pass the frame metadata as
- *  well as an array of pointers (one for each channel) pointing to the
- *  decoded audio.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__stream_decoder_set_write_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteCallback value);
-
-/** Set the metadata callback.
- *  The supplied function will be called when the decoder has decoded a metadata
- *  block.  In a valid FLAC file there will always be one STREAMINFO block,
- *  followed by zero or more other metadata blocks.  These will be supplied
- *  by the decoder in the same order as they appear in the stream and always
- *  before the first audio frame (i.e. write callback).  The metadata block
- *  that is passed in must not be modified, and it doesn't live beyond the
- *  callback, so you should make a copy of it with
- *  FLAC__metadata_object_clone() if you will need it elsewhere.  Since
- *  metadata blocks can potentially be large, by default the decoder only
- *  calls the metadata callback for the STREAMINFO block; you can instruct
- *  the decoder to pass or filter other blocks with
- *  FLAC__stream_decoder_set_metadata_*() calls.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderMetadataCallback value);
-
-/** Set the error callback.
- *  The supplied function will be called whenever an error occurs during
- *  decoding.
+/** Set the "MD5 signature checking" flag.  If \c true, the decoder will
+ *  compute the MD5 signature of the unencoded audio data while decoding
+ *  and compare it to the signature from the STREAMINFO block, if it
+ *  exists, during FLAC__stream_decoder_finish().
  *
- * \note
- * The callback is mandatory and must be set before initialization.
+ *  MD5 signature checking will be turned off (until the next
+ *  FLAC__stream_decoder_reset()) if there is no signature in the
+ *  STREAMINFO block or when a seek is attempted.
  *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__stream_decoder_set_error_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
+ *  Clients that do not use the MD5 check should leave this off to speed
+ *  up decoding.
  *
- * \default \c NULL
+ * \default \c false
  * \param  decoder  A decoder instance to set.
- * \param  value    See above.
+ * \param  value    Flag value (see above).
  * \assert
  *    \code decoder != NULL \endcode
  * \retval FLAC__bool
  *    \c false if the decoder is already initialized, else \c true.
  */
-FLAC_API FLAC__bool FLAC__stream_decoder_set_client_data(FLAC__StreamDecoder *decoder, void *value);
+FLAC_API FLAC__bool FLAC__stream_decoder_set_md5_checking(FLAC__StreamDecoder *decoder, FLAC__bool value);
 
 /** Direct the decoder to pass on all metadata blocks of type \a type.
  *
@@ -630,6 +787,32 @@ FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__Str
  */
 FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder);
 
+/** Get the "MD5 signature checking" flag.
+ *  This is the value of the setting, not whether or not the decoder is
+ *  currently checking the MD5 (remember, it can be turned off automatically
+ *  by a seek).  When the decoder is reset the flag will be restored to the
+ *  value returned by this function.
+ *
+ * \param  decoder  A decoder instance to query.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ *    See above.
+ */
+FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDecoder *decoder);
+
+/** Get the total number of samples in the stream being decoded.
+ *  Will only be valid after decoding has started and will contain the
+ *  value from the \c STREAMINFO block.  A value of \c 0 means "unknown".
+ *
+ * \param  decoder  A decoder instance to query.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval unsigned
+ *    See above.
+ */
+FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder);
+
 /** Get the current number of channels in the stream being decoded.
  *  Will only be valid after decoding has started and will contain the
  *  value from the most recently decoded frame header.
@@ -690,22 +873,187 @@ FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder
  */
 FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder);
 
+/** Returns the decoder's current read position within the stream.
+ *  The position is the byte offset from the start of the stream.
+ *  Bytes before this position have been fully decoded.  Note that
+ *  there may still be undecoded bytes in the decoder's read FIFO.
+ *  The returned position is correct even after a seek.
+ *
+ * \param  decoder   A decoder instance to query.
+ * \param  position  Address at which to return the desired position.
+ * \assert
+ *    \code decoder != NULL \endcode
+ *    \code position != NULL \endcode
+ * \retval FLAC__bool
+ *    \c true if successful, \c false if there was an error from
+ *    the 'tell' callback or it returned
+ *    \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED.
+ */
+FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position);
+
 /** Initialize the decoder instance.
- *  Should be called after FLAC__stream_decoder_new() and
+ *
+ *  This flavor of initialization sets up the decoder to decode from a stream.
+ *  I/O is performed via callbacks to the client.  For decoding from a plain file
+ *  via filename or open FILE*, FLAC__stream_decoder_init_file() and
+ *  FLAC__stream_decoder_init_FILE() provide a simpler interface.
+ *
+ *  This function should be called after FLAC__stream_decoder_new() and
  *  FLAC__stream_decoder_set_*() but before any of the
  *  FLAC__stream_decoder_process_*() functions.  Will set and return the
  *  decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
  *  if initialization succeeded.
  *
- * \param  decoder  An uninitialized decoder instance.
+ * \param  decoder            An uninitialized decoder instance.
+ * \param  read_callback      See FLAC__StreamDecoderReadCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  seek_callback      See FLAC__StreamDecoderSeekCallback.  This
+ *                            pointer may be \c NULL if seeking is not
+ *                            supported.  If \a seek_callback is not \c NULL then a
+ *                            \a tell_callback, \a length_callback, and \a eof_callback must also be supplied.
+ *                            Alternatively, a dummy seek callback that just
+ *                            returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  tell_callback      See FLAC__StreamDecoderTellCallback.  This
+ *                            pointer may be \c NULL if not supported by the client.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a tell_callback must also be supplied.
+ *                            Alternatively, a dummy tell callback that just
+ *                            returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  length_callback    See FLAC__StreamDecoderLengthCallback.  This
+ *                            pointer may be \c NULL if not supported by the client.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a length_callback must also be supplied.
+ *                            Alternatively, a dummy length callback that just
+ *                            returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  eof_callback       See FLAC__StreamDecoderEofCallback.  This
+ *                            pointer may be \c NULL if not supported by the client.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a eof_callback must also be supplied.
+ *                            Alternatively, a dummy length callback that just
+ *                            returns \c false
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  write_callback     See FLAC__StreamDecoderWriteCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  metadata_callback  See FLAC__StreamDecoderMetadataCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  error_callback     See FLAC__StreamDecoderErrorCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
  * \assert
  *    \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA if initialization was
- *    successful; see FLAC__StreamDecoderState for the meanings of other
- *    return values.
+ * \retval FLAC__StreamDecoderInitStatus
+ *    \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamDecoderInitStatus for the meanings of other return values.
+ */
+FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
+       FLAC__StreamDecoder *decoder,
+       FLAC__StreamDecoderReadCallback read_callback,
+       FLAC__StreamDecoderSeekCallback seek_callback,
+       FLAC__StreamDecoderTellCallback tell_callback,
+       FLAC__StreamDecoderLengthCallback length_callback,
+       FLAC__StreamDecoderEofCallback eof_callback,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+);
+
+/** Initialize the decoder instance.
+ *
+ *  This flavor of initialization sets up the decoder to decode from a plain
+ *  file.  For non-stdio streams, you must use
+ *  FLAC__stream_decoder_init_stream() and provide callbacks for the I/O.
+ *
+ *  This function should be called after FLAC__stream_decoder_new() and
+ *  FLAC__stream_decoder_set_*() but before any of the
+ *  FLAC__stream_decoder_process_*() functions.  Will set and return the
+ *  decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
+ *  if initialization succeeded.
+ *
+ * \param  decoder            An uninitialized decoder instance.
+ * \param  file               An open FLAC file.  The file should have been
+ *                            opened with mode \c "rb" and rewound.  The file
+ *                            becomes owned by the decoder and should not be
+ *                            manipulated by the client while decoding.
+ *                            Unless \a file is \c stdin, it will be closed
+ *                            when FLAC__stream_decoder_finish() is called.
+ *                            Note however that seeking will not work when
+ *                            decoding from \c stdout since it is not seekable.
+ * \param  write_callback     See FLAC__StreamDecoderWriteCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  metadata_callback  See FLAC__StreamDecoderMetadataCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  error_callback     See FLAC__StreamDecoderErrorCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code decoder != NULL \endcode
+ *    \code file != NULL \endcode
+ * \retval FLAC__StreamDecoderInitStatus
+ *    \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamDecoderInitStatus for the meanings of other return values.
  */
-FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder);
+FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
+       FLAC__StreamDecoder *decoder,
+       FILE *file,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+);
+
+/** Initialize the decoder instance.
+ *
+ *  This flavor of initialization sets up the decoder to decode from a plain
+ *  file.  If POSIX fopen() semantics are not sufficient, (for example, with
+ *  Unicode filenames on Windows), you must use
+ *  FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream()
+ *  and provide callbacks for the I/O.
+ *
+ *  This function should be called after FLAC__stream_decoder_new() and
+ *  FLAC__stream_decoder_set_*() but before any of the
+ *  FLAC__stream_decoder_process_*() functions.  Will set and return the
+ *  decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
+ *  if initialization succeeded.
+ *
+ * \param  decoder            An uninitialized decoder instance.
+ * \param  filename           The name of the file to decode from.  The file will
+ *                            be opened with fopen().  Use \c NULL to decode from
+ *                            \c stdin.  Note that \c stdin is not seekable.
+ * \param  write_callback     See FLAC__StreamDecoderWriteCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  metadata_callback  See FLAC__StreamDecoderMetadataCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  error_callback     See FLAC__StreamDecoderErrorCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval FLAC__StreamDecoderInitStatus
+ *    \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamDecoderInitStatus for the meanings of other return values.
+ */
+FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
+       FLAC__StreamDecoder *decoder,
+       const char *filename,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+);
 
 /** Finish the decoding process.
  *  Flushes the decoding buffer, releases resources, resets the decoder
@@ -720,19 +1068,26 @@ FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder
  * \param  decoder  An uninitialized decoder instance.
  * \assert
  *    \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if MD5 checking is on AND a STREAMINFO block was available
+ *    AND the MD5 signature in the STREAMINFO block was non-zero AND the
+ *    signature does not match the one computed by the decoder; else
+ *    \c true.
  */
-FLAC_API void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder);
+FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder);
 
 /** Flush the stream input.
  *  The decoder's input buffer will be cleared and the state set to
- *  \c FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC.
+ *  \c FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC.  This will also turn
+ *  off MD5 checking.
  *
  * \param  decoder  A decoder instance.
  * \assert
  *    \code decoder != NULL \endcode
  * \retval FLAC__bool
  *    \c true if successful, else \c false if a memory allocation
- *    error occurs.
+ *    error occurs (in which case the state will be set to
+ *    \c FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR).
  */
 FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder);
 
@@ -741,14 +1096,31 @@ FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder);
  *  \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA.  This is similar to
  *  FLAC__stream_decoder_finish() except that the settings are
  *  preserved; there is no need to call FLAC__stream_decoder_init()
- *  before decoding again.
+ *  before decoding again.  MD5 checking will be restored to its original
+ *  setting.
+ *
+ *  If the decoder is seekable, or was initialized with
+ *  FLAC__stream_decoder_init_FILE() or FLAC__stream_decoder_init_file(),
+ *  the decoder will also attempt to seek to the beginning of the file.
+ *  If this rewind fails, this function will return \c false.  It follows
+ *  that FLAC__stream_decoder_reset() cannot be used when decoding from
+ *  \c stdin.
+ *
+ *  If the decoder was initialized with FLAC__stream_encoder_init_stream()
+ *  and is not seekable (i.e. no seek callback was provided or the seek
+ *  callback returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED), it
+ *  is the duty of the client to start feeding data from the beginning of
+ *  the stream on the next FLAC__stream_decoder_process() or
+ *  FLAC__stream_decoder_process_interleaved() call.
  *
  * \param  decoder  A decoder instance.
  * \assert
  *    \code decoder != NULL \endcode
  * \retval FLAC__bool
- *    \c true if successful, else \c false if a memory allocation
- *    error occurs.
+ *    \c true if successful, else \c false if a memory allocation occurs
+ *    (in which case the state will be set to
+ *    \c FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR) or a seek error
+ *    occurs (the state will be unchanged).
  */
 FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder);
 
@@ -869,6 +1241,24 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__Strea
  */
 FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder);
 
+/** Flush the input and seek to an absolute sample.
+ *  Decoding will resume at the given sample.  Note that because of
+ *  this, the next write callback may contain a partial block.  The
+ *  client must support seeking the input or this function will fail
+ *  and return \c false.  Furthermore, if the decoder state is
+ *  \c FLAC__STREAM_DECODER_SEEK_ERROR, then the decoder must be flushed
+ *  with FLAC__stream_decoder_flush() or reset with
+ *  FLAC__stream_decoder_reset() before decoding can continue.
+ *
+ * \param  decoder  A decoder instance.
+ * \param  sample   The target sample number to seek to.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ *    \c true if successful, else \c false.
+ */
+FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *decoder, FLAC__uint64 sample);
+
 /* \} */
 
 #ifdef __cplusplus
index dcf879c..20d7375 100644 (file)
@@ -32,6 +32,7 @@
 #ifndef FLAC__STREAM_ENCODER_H
 #define FLAC__STREAM_ENCODER_H
 
+#include <stdio.h> /* for FILE */
 #include "export.h"
 #include "format.h"
 #include "stream_decoder.h"
@@ -55,29 +56,23 @@ extern "C" {
  *  \ingroup flac
  *
  *  \brief
- *  This module describes the three encoder layers provided by libFLAC.
- *
- * For encoding FLAC streams, libFLAC provides three layers of access.  The
- * lowest layer is non-seekable stream-level encoding, the next is seekable
- * stream-level encoding, and the highest layer is file-level encoding.  The
- * interfaces are described in the \link flac_stream_encoder stream encoder
- * \endlink, \link flac_seekable_stream_encoder seekable stream encoder
- * \endlink, and \link flac_file_encoder file encoder \endlink modules
- * respectively.  Typically you will choose the highest layer that your input
- * source will support.
- * The stream encoder relies on callbacks for writing the data and
- * metadata. The file encoder provides these callbacks internally and you
- * need only supply the filename.
- *
- * The stream encoder relies on callbacks for writing the data and has no
- * provisions for seeking the output.  The seekable stream encoder wraps
- * the stream encoder and also automaticallay handles the writing back of
- * metadata discovered while encoding.  However, you must provide extra
- * callbacks for seek-related operations on your output, like seek and
- * tell.  The file encoder wraps the seekable stream encoder and supplies
- * all of the callbacks internally, simplifying the processing of standard
- * files.  The only callback exposed is for progress reporting, and that
- * is optional.
+ *  This module describes the two encoder layers provided by libFLAC.
+ *
+ * libFLAC provides two ways of encoding FLAC streams.  There is a @@@@@@frame encoder which encodes single frames at a time, and a stream encoder which encodes whole streams.
+ *
+ * @@@@@@TODO frame encoder
+ *
+ * The stream encoder can be used encode complete streams either to the
+ * client via callbacks, or directly to a file, depending on how it is
+ * initialized.  When encoding via callbacks, the client provides a write
+ * callback which will be called whenever FLAC data is ready to be written.
+ * If the client also supplies a seek callback, the encoder will also
+ * automatically handle the writing back of metadata discovered while
+ * encoding, like stream info, seek points offsets, etc.  When encoding to
+ * a file, the client needs only supply a filename or open \c FILE* and an
+ * optional progress callback for periodic notification of progress; the
+ * write and seek callbacks are supplied internally.  For more info see the
+ * \link flac_stream_encoder stream encoder \endlink module.
  */
 
 /** \defgroup flac_stream_encoder FLAC/stream_encoder.h: stream encoder interface
@@ -90,18 +85,21 @@ extern "C" {
  * The basic usage of this encoder is as follows:
  * - The program creates an instance of an encoder using
  *   FLAC__stream_encoder_new().
- * - The program overrides the default settings and sets callbacks using
+ * - The program overrides the default settings using
  *   FLAC__stream_encoder_set_*() functions.
  * - The program initializes the instance to validate the settings and
- *   prepare for encoding using FLAC__stream_encoder_init().
+ *   prepare for encoding using FLAC__stream_encoder_init_stream() or
+ *   FLAC__stream_encoder_init_FILE() or FLAC__stream_encoder_init_file(),
+ *   depending on the nature of the output.
  * - The program calls FLAC__stream_encoder_process() or
  *   FLAC__stream_encoder_process_interleaved() to encode data, which
  *   subsequently calls the callbacks when there is encoder data ready
  *   to be written.
  * - The program finishes the encoding with FLAC__stream_encoder_finish(),
  *   which causes the encoder to encode any data still in its input pipe,
- *   call the metadata callback with the final encoding statistics, and
- *   finally reset the encoder to the uninitialized state.
+ *   update the metadata with the final encoding statistics if output
+ *   seeking is possible, and finally reset the encoder to the
+ *   uninitialized state.
  * - The instance may be used again or deleted with
  *   FLAC__stream_encoder_delete().
  *
@@ -109,8 +107,9 @@ extern "C" {
  * \link flac_stream_decoder stream decoder \endlink, but has fewer
  * callbacks and more options.  Typically the user will create a new
  * instance by calling FLAC__stream_encoder_new(), then set the necessary
- * parameters and callbacks with FLAC__stream_encoder_set_*(), and
- * initialize it by calling FLAC__stream_encoder_init().
+ * parameters with FLAC__stream_encoder_set_*(), and initialize it by
+ * calling FLAC__stream_encoder_init_stream() or
+ * FLAC__stream_encoder_init_file() or FLAC__stream_encoder_init_FILE().
  *
  * Unlike the decoders, the stream encoder has many options that can
  * affect the speed and compression ratio.  When setting these parameters
@@ -118,26 +117,32 @@ extern "C" {
  * <A HREF="../documentation.html#format">user-level documentation</A>
  * or the <A HREF="../format.html">formal description</A>).  The
  * FLAC__stream_encoder_set_*() functions themselves do not validate the
- * values as many are interdependent.  The FLAC__stream_encoder_init()
- * function will do this, so make sure to pay attention to the state
- * returned by FLAC__stream_encoder_init() to make sure that it is
- * FLAC__STREAM_ENCODER_OK.  Any parameters that are not set before
- * FLAC__stream_encoder_init() will take on the defaults from the
- * constructor.
- *
- * The user must provide function pointers for the following callbacks:
- *
- * - Write callback - This function is called by the encoder anytime there
- *   is raw encoded data to write.  It may include metadata mixed with
- *   encoded audio frames and the data is not guaranteed to be aligned on
- *   frame or metadata block boundaries.
- * - Metadata callback - This function is called once at the end of
- *   encoding with the populated STREAMINFO structure.  This is so file
- *   encoders can seek back to the beginning of the file and write the
- *   STREAMINFO block with the correct statistics after encoding (like
- *   minimum/maximum frame size).
- *
- * The call to FLAC__stream_encoder_init() currently will also immediately
+ * values as many are interdependent.  The FLAC__stream_encoder_init_*()
+ * functions will do this, so make sure to pay attention to the state
+ * returned by FLAC__stream_encoder_init_*() to make sure that it is
+ * FLAC__STREAM_ENCODER_INIT_STATUS_OK.  Any parameters that are not set
+ * before FLAC__stream_encoder_init_*() will take on the defaults from
+ * the constructor.
+ *
+ * There are three initialization functions, one for setting up the encoder
+ * to encode FLAC data to the client via callbacks, and two for encoding
+ * directly to a file.
+ *
+ * For encoding via callbacks, use FLAC__stream_encoder_init_stream().
+ * You must also supply a write callback which will be called anytime
+ * there is raw encoded data to write.  If the client can seek the output
+ * it is best to also supply seek and tell callbacks, as this allows the
+ * encoder to go back after encoding is finished to write back
+ * information that was collected while encoding, like seek point offsets,
+ * frame sizes, etc.
+ *
+ * For encoding directly to a file, use FLAC__stream_encoder_init_FILE()
+ * or FLAC__stream_encoder_init_file().  Then you must only supply a
+ * filename or open \c FILE*; the encoder will handle all the callbacks
+ * internally.  You may also supply a progress callback for periodic
+ * notification of the encoding progress.
+ *
+ * The call to FLAC__stream_encoder_init_*() currently will also immediately
  * call the write callback several times, once with the \c fLaC signature,
  * and once for each encoded metadata block.
  *
@@ -177,6 +182,14 @@ extern "C" {
  * for the specification of metadata blocks and their lengths.
  *
  * \note
+ * If you are writing the FLAC data to a file via callbacks, make sure it
+ * is open for update (e.g. mode "w+" for stdio streams).  This is because
+ * after the first encoding pass, the encoder will try to seek back to the
+ * beginning of the stream, to the STREAMINFO block, to write some data
+ * there.  (If using FLAC__stream_encoder_init_file() or
+ * FLAC__stream_encoder_init_FILE(), the file is managed internally.)
+ *
+ * \note
  * The "set" functions may only be called when the encoder is in the
  * state FLAC__STREAM_ENCODER_UNINITIALIZED, i.e. after
  * FLAC__stream_encoder_new() or FLAC__stream_encoder_finish(), but
@@ -185,20 +198,30 @@ extern "C" {
  *
  * \note
  * FLAC__stream_encoder_finish() resets all settings to the constructor
- * defaults, including the callbacks.
+ * defaults.
  *
  * \{
  */
 
 
-/** State values for a FLAC__StreamEncoder
+/** State values for a FLAC__StreamEncoder.
+ *
+ * The encoder's state can be obtained by calling FLAC__stream_encoder_get_state().
  *
- *  The encoder's state can be obtained by calling FLAC__stream_encoder_get_state().
+ * If the encoder gets into any other state besides \c FLAC__STREAM_ENCODER_OK
+ * or \c FLAC__STREAM_ENCODER_UNINITIALIZED, it becomes invalid for encoding and
+ * must be deleted with FLAC__stream_encoder_delete().
  */
 typedef enum {
 
        FLAC__STREAM_ENCODER_OK = 0,
-       /**< The encoder is in the normal OK state. */
+       /**< The encoder is in the normal OK state and samples can be processed. */
+
+       FLAC__STREAM_ENCODER_UNINITIALIZED,
+       /**< The encoder is in the uninitialized state; one of the
+        * FLAC__stream_encoder_init_*() functions must be called before samples
+        * can be processed.
+        */
 
        FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR,
        /**< An error occurred in the underlying verify stream decoder;
@@ -210,49 +233,81 @@ typedef enum {
         * audio signal and the decoded audio signal.
         */
 
-       FLAC__STREAM_ENCODER_INVALID_CALLBACK,
-       /**< The encoder was initialized before setting all the required callbacks. */
+       FLAC__STREAM_ENCODER_CLIENT_ERROR,
+       /**< One of the callbacks returned a fatal error. */
+
+       FLAC__STREAM_ENCODER_IO_ERROR,
+       /**< An I/O error occurred while opening/reading/writing a file.
+        * Check \c errno.
+        */
+
+       FLAC__STREAM_ENCODER_FRAMING_ERROR,
+       /**< An error occurred while writing the stream; usually, the
+        * write_callback returned an error.
+        */
+
+       FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR
+       /**< Memory allocation failed. */
+
+} FLAC__StreamEncoderState;
+
+/** Maps a FLAC__StreamEncoderState to a C string.
+ *
+ *  Using a FLAC__StreamEncoderState as the index to this array
+ *  will give the string equivalent.  The contents should not be modified.
+ */
+extern FLAC_API const char * const FLAC__StreamEncoderStateString[];
+
+/** Possible return values for the FLAC__stream_encoder_init_*() functions.
+ */
+typedef enum {
+
+       FLAC__STREAM_ENCODER_INIT_STATUS_OK = 0,
+       /**< Initialization was successful. */
 
-       FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS,
+       FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR,
+       /**< General failure to set up encoder; call FLAC__stream_encoder_get_state() for cause. */
+
+       FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS,
+       /**< A required callback was not supplied. */
+
+       FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS,
        /**< The encoder has an invalid setting for number of channels. */
 
-       FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE,
+       FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE,
        /**< The encoder has an invalid setting for bits-per-sample.
         * FLAC supports 4-32 bps but the reference encoder currently supports
         * only up to 24 bps.
         */
 
-       FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE,
+       FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE,
        /**< The encoder has an invalid setting for the input sample rate. */
 
-       FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE,
+       FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE,
        /**< The encoder has an invalid setting for the block size. */
 
-       FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER,
+       FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER,
        /**< The encoder has an invalid setting for the maximum LPC order. */
 
-       FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION,
+       FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION,
        /**< The encoder has an invalid setting for the precision of the quantized linear predictor coefficients. */
 
-       FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH,
+       FLAC__STREAM_ENCODER_INIT_STATUS_MID_SIDE_CHANNELS_MISMATCH,
        /**< Mid/side coding was specified but the number of channels is not equal to 2. */
 
-       FLAC__STREAM_ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH,
+       FLAC__STREAM_ENCODER_INIT_STATUS_MID_SIDE_SAMPLE_SIZE_MISMATCH,
        /**< Deprecated. */
 
-       FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE,
+       FLAC__STREAM_ENCODER_INIT_STATUS_ILLEGAL_MID_SIDE_FORCE,
        /**< Loose mid/side coding was specified but mid/side coding was not. */
 
-       FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER,
+       FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER,
        /**< The specified block size is less than the maximum LPC order. */
 
-       FLAC__STREAM_ENCODER_NOT_STREAMABLE,
+       FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE,
        /**< The encoder is bound to the "streamable subset" but other settings violate it. */
 
-       FLAC__STREAM_ENCODER_FRAMING_ERROR,
-       /**< An error occurred while writing the stream; usually, the write_callback returned an error. */
-
-       FLAC__STREAM_ENCODER_INVALID_METADATA,
+       FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA,
        /**< The metadata input to the encoder is invalid, in one of the following ways:
         * - FLAC__stream_encoder_set_metadata() was called with a null pointer but a block count > 0
         * - One of the metadata blocks contains an undefined type
@@ -261,32 +316,20 @@ typedef enum {
         * - It contains more than one SEEKTABLE block or more than one VORBIS_COMMENT block
         */
 
-       FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING,
-       /**< An error occurred while writing the stream; usually, the write_callback returned an error. */
-
-       FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING,
-       /**< The write_callback returned an error. */
-
-       FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
-
-       FLAC__STREAM_ENCODER_ALREADY_INITIALIZED,
-       /**< FLAC__stream_encoder_init() was called when the encoder was
+       FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED
+       /**< FLAC__stream_encoder_init_*() was called when the encoder was
         * already initialized, usually because
         * FLAC__stream_encoder_finish() was not called.
         */
 
-       FLAC__STREAM_ENCODER_UNINITIALIZED
-       /**< The encoder is in the uninitialized state. */
-
-} FLAC__StreamEncoderState;
+} FLAC__StreamEncoderInitStatus;
 
-/** Maps a FLAC__StreamEncoderState to a C string.
+/** Maps a FLAC__StreamEncoderInitStatus to a C string.
  *
- *  Using a FLAC__StreamEncoderState as the index to this array
+ *  Using a FLAC__StreamEncoderInitStatus as the index to this array
  *  will give the string equivalent.  The contents should not be modified.
  */
-extern FLAC_API const char * const FLAC__StreamEncoderStateString[];
+extern FLAC_API const char * const FLAC__StreamEncoderInitStatusString[];
 
 /** Return values for the FLAC__StreamEncoder write callback.
  */
@@ -307,6 +350,51 @@ typedef enum {
  */
 extern FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[];
 
+/** Return values for the FLAC__StreamEncoder seek callback.
+ */
+typedef enum {
+
+       FLAC__STREAM_ENCODER_SEEK_STATUS_OK,
+       /**< The seek was OK and encoding can continue. */
+
+       FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR,
+       /**< An unrecoverable error occurred. */
+
+       FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED
+       /**< Client does not support seeking. */
+
+} FLAC__StreamEncoderSeekStatus;
+
+/** Maps a FLAC__StreamEncoderSeekStatus to a C string.
+ *
+ *  Using a FLAC__StreamEncoderSeekStatus as the index to this array
+ *  will give the string equivalent.  The contents should not be modified.
+ */
+extern FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[];
+
+
+/** Return values for the FLAC__StreamEncoder tell callback.
+ */
+typedef enum {
+
+       FLAC__STREAM_ENCODER_TELL_STATUS_OK,
+       /**< The tell was OK and encoding can continue. */
+
+       FLAC__STREAM_ENCODER_TELL_STATUS_ERROR,
+       /**< An unrecoverable error occurred. */
+
+       FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED
+       /**< Client does not support seeking. */
+
+} FLAC__StreamEncoderTellStatus;
+
+/** Maps a FLAC__StreamEncoderTellStatus to a C string.
+ *
+ *  Using a FLAC__StreamEncoderTellStatus as the index to this array
+ *  will give the string equivalent.  The contents should not be modified.
+ */
+extern FLAC_API const char * const FLAC__StreamEncoderTellStatusString[];
+
 
 /***********************************************************************
  *
@@ -326,32 +414,126 @@ typedef struct {
 } FLAC__StreamEncoder;
 
 /** Signature for the write callback.
- *  See FLAC__stream_encoder_set_write_callback() for more info.
+ *
+ *  A function pointer matching this signature must be passed to
+ *  FLAC__stream_encoder_init_stream().  The supplied function will be called
+ *  by the encoder anytime there is raw encoded data ready to write.  It may
+ *  include metadata mixed with encoded audio frames and the data is not
+ *  guaranteed to be aligned on frame or metadata block boundaries.
+ *
+ *  The only duty of the callback is to write out the \a bytes worth of data
+ *  in \a buffer to the current position in the output stream.  The arguments
+ *  \a samples and \a current_frame are purely informational.  If \a samples
+ *  is greater than \c 0, then \a current_frame will hold the current frame
+ *  number that is being written; otherwise it indicates that the write
+ *  callback is being called to write metadata.
+ *
+ * \note In general, FLAC__StreamEncoder functions which change the
+ * state should not be called on the \a encoder while in the callback.
  *
  * \param  encoder  The encoder instance calling the callback.
  * \param  buffer   An array of encoded data of length \a bytes.
  * \param  bytes    The byte length of \a buffer.
  * \param  samples  The number of samples encoded by \a buffer.
- *                  \c 0 has a special meaning; see
- *                  FLAC__stream_encoder_set_write_callback().
+ *                  \c 0 has a special meaning; see above.
  * \param  current_frame  The number of the current frame being encoded.
  * \param  client_data  The callee's client data set through
- *                      FLAC__stream_encoder_set_client_data().
+ *                      FLAC__stream_encoder_init_*().
  * \retval FLAC__StreamEncoderWriteStatus
  *    The callee's return status.
  */
 typedef FLAC__StreamEncoderWriteStatus (*FLAC__StreamEncoderWriteCallback)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
 
+/** Signature for the seek callback.
+ *
+ *  A function pointer matching this signature may be passed to
+ *  FLAC__stream_encoder_init_stream().  The supplied function will be called
+ *  when the encoder needs to seek the output stream.  The encoder will pass
+ *  the absolute byte offset to seek to, 0 meaning the beginning of the stream.
+ *
+ * \note In general, FLAC__StreamEncoder functions which change the
+ * state should not be called on the \a encoder while in the callback.
+ *
+ * \param  encoder  The encoder instance calling the callback.
+ * \param  absolute_byte_offset  The offset from the beginning of the stream
+ *                               to seek to.
+ * \param  client_data  The callee's client data set through
+ *                      FLAC__stream_encoder_init_*().
+ * \retval FLAC__StreamEncoderSeekStatus
+ *    The callee's return status.
+ */
+typedef FLAC__StreamEncoderSeekStatus (*FLAC__StreamEncoderSeekCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+
+/** Signature for the tell callback.
+ *
+ *  A function pointer matching this signature may be passed to
+ *  FLAC__stream_encoder_init_stream().  The supplied function will be called
+ *  when the encoder needs to know the current position of the output stream.
+ *
+ * \warning
+ * The callback must return the true current byte offset of the output to
+ * which the encoder is writing.  If you are buffering the output, make
+ * sure and take this into account.  If you are writing directly to a
+ * FILE* from your write callback, ftell() is sufficient.  If you are
+ * writing directly to a file descriptor from your write callback, you
+ * can use lseek(fd, SEEK_CUR, 0).  The encoder may later seek back to
+ * these points to rewrite metadata after encoding.
+ *
+ * \note In general, FLAC__StreamEncoder functions which change the
+ * state should not be called on the \a encoder while in the callback.
+ *
+ * \param  encoder  The encoder instance calling the callback.
+ * \param  absolute_byte_offset  The address at which to store the current
+ *                               position of the output.
+ * \param  client_data  The callee's client data set through
+ *                      FLAC__stream_encoder_init_*().
+ * \retval FLAC__StreamEncoderTellStatus
+ *    The callee's return status.
+ */
+typedef FLAC__StreamEncoderTellStatus (*FLAC__StreamEncoderTellCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+
 /** Signature for the metadata callback.
- *  See FLAC__stream_encoder_set_metadata_callback() for more info.
+ *
+ *  A function pointer matching this signature may be passed to
+ *  FLAC__stream_encoder_init_stream().  The supplied function will be called
+ *  once at the end of encoding with the populated STREAMINFO structure.  This
+ *  is so the client can seek back to the beginning of the file and write the
+ *  STREAMINFO block with the correct statistics after encoding (like
+ *  minimum/maximum frame size and total samples).
+ *
+ * \note In general, FLAC__StreamEncoder functions which change the
+ * state should not be called on the \a encoder while in the callback.
  *
  * \param  encoder      The encoder instance calling the callback.
  * \param  metadata     The final populated STREAMINFO block.
  * \param  client_data  The callee's client data set through
- *                      FLAC__stream_encoder_set_client_data().
+ *                      FLAC__stream_encoder_init_*().
  */
 typedef void (*FLAC__StreamEncoderMetadataCallback)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
 
+/** Signature for the progress callback.
+ *
+ *  A function pointer matching this signature may be passed to
+ *  FLAC__stream_encoder_init_file() or FLAC__stream_encoder_init_FILE().
+ *  The supplied function will be called when the encoder has finished
+ *  writing a frame.  The \c total_frames_estimate argument to the
+ *  callback will be based on the value from
+ *  FLAC__file_encoder_set_total_samples_estimate().
+ *
+ * \note In general, FLAC__StreamEncoder functions which change the
+ * state should not be called on the \a encoder while in the callback.
+ *
+ * \param  encoder          The encoder instance calling the callback.
+ * \param  bytes_written    Bytes written so far.
+ * \param  samples_written  Samples written so far.
+ * \param  frames_written   Frames written so far.
+ * \param  total_frames_estimate  The estimate of the total number of
+ *                                frames to be written.
+ * \param  client_data      The callee's client data set through
+ *                          FLAC__stream_encoder_init_*().
+ */
+typedef void (*FLAC__StreamEncoderProgressCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
+
 
 /***********************************************************************
  *
@@ -691,9 +873,10 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__Stream
 /** Set the metadata blocks to be emitted to the stream before encoding.
  *  A value of \c NULL, \c 0 implies no metadata; otherwise, supply an
  *  array of pointers to metadata blocks.  The array is non-const since
- *  the encoder may need to change the \a is_last flag inside them.
- *  Otherwise, the encoder will not modify or free the blocks.  It is up
- *  to the caller to free the metadata blocks after encoding.
+ *  the encoder may need to change the \a is_last flag inside them, and
+ *  in some cases update seek point offsets.  Otherwise, the encoder will
+ *  not modify or free the blocks.  It is up to the caller to free the
+ *  metadata blocks after encoding.
  *
  * \note
  * The encoder stores only the \a metadata pointer; the passed-in array
@@ -706,11 +889,34 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__Stream
  *
  * \note
  * By default the encoder does not create a SEEKTABLE.  If one is supplied
- * in the \a metadata array it will be written verbatim.  However by itself
- * this is not very useful as the user will not know the stream offsets for
- * the seekpoints ahead of time.  You must use the seekable stream encoder
- * to generate a legal seektable
- * (see FLAC__seekable_stream_encoder_set_metadata())
+ * in the \a metadata array, but the client has specified that it does not
+ * support seeking, then the SEEKTABLE will be written verbatim.  However
+ * by itself this is not very useful as the client will not know the stream
+ * offsets for the seekpoints ahead of time.  In order to get a proper
+ * seektable the client must support seeking.  See next note.
+ *
+ * \note
+ * SEEKTABLE blocks are handled specially.  Since you will not know
+ * the values for the seek point stream offsets, you should pass in
+ * a SEEKTABLE 'template', that is, a SEEKTABLE object with the
+ * required sample numbers (or placeholder points), with \c 0 for the
+ * \a frame_samples and \a stream_offset fields for each point.  If the
+ * client has specified that it supports seeking by providing a seek
+ * callback to FLAC__stream_encoder_init_stream() (or by using
+ * FLAC__stream_encoder_init_file() or FLAC__stream_encoder_init_FILE()),
+ * then while it is encoding the encoder will fill the stream offsets in
+ * for you and when encoding is finished, it will seek back and write the
+ * real values into the SEEKTABLE block in the stream.  There are helper
+ * routines for manipulating seektable template blocks; see metadata.h:
+ * FLAC__metadata_object_seektable_template_*().  If the client does
+ * not support seeking, the SEEKTABLE will have inaccurate offsets which
+ * will slow down or remove the ability to seek in the FLAC stream.
+ *
+ * \note
+ * The encoder instance \b will modify the first \c SEEKTABLE block
+ * as it transforms the template to a valid seektable while encoding,
+ * but it is still up to the caller to free all metadata blocks after
+ * encoding.
  *
  * \note
  * A VORBIS_COMMENT block may be supplied.  The vendor string in it
@@ -731,68 +937,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__Stream
  */
 FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
 
-/** Set the write callback.
- *  The supplied function will be called by the encoder anytime there is raw
- *  encoded data ready to write.  It may include metadata mixed with encoded
- *  audio frames and the data is not guaranteed to be aligned on frame or
- *  metadata block boundaries.
- *
- *  The only duty of the callback is to write out the \a bytes worth of data
- *  in \a buffer to the current position in the output stream.  The arguments
- *  \a samples and \a current_frame are purely informational.  If \a samples
- *  is greater than \c 0, then \a current_frame will hold the current frame
- *  number that is being written; otherwise, the write callback is being called
- *  to write metadata.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__stream_encoder_set_write_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback value);
-
-/** Set the metadata callback.
- *  The supplied function will be called once at the end of encoding with
- *  the populated STREAMINFO structure.  This is so file encoders can seek
- *  back to the beginning of the file and write the STREAMINFO block with
- *  the correct statistics after encoding (like minimum/maximum frame size
- *  and total samples).
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderMetadataCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-FLAC_API FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, void *value);
-
 /** Get the current encoder state.
  *
  * \param  encoder  An encoder instance to query.
@@ -1021,24 +1165,141 @@ FLAC_API unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC
 FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder);
 
 /** Initialize the encoder instance.
- *  Should be called after FLAC__stream_encoder_new() and
+ *
+ *  This flavor of initialization sets up the encoder to encode to a stream.
+ *  I/O is performed via callbacks to the client.  For encoding to a plain file
+ *  via filename or open \c FILE*, FLAC__stream_encoder_init_file() and
+ *  FLAC__stream_encoder_init_FILE() provide a simpler interface.
+ *
+ *  This function should be called after FLAC__stream_encoder_new() and
  *  FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process()
- *  or FLAC__stream_encoder_process_interleaved().  Will set and return
- *  the encoder state, which will be FLAC__STREAM_ENCODER_OK if
+ *  or FLAC__stream_encoder_process_interleaved().
  *  initialization succeeded.
  *
- *  The call to FLAC__stream_encoder_init() currently will also immediately
+ *  The call to FLAC__stream_encoder_init_stream() currently will also immediately
  *  call the write callback several times, once with the \c fLaC signature,
  *  and once for each encoded metadata block.
  *
- * \param  encoder  An uninitialized encoder instance.
+ * \param  encoder            An uninitialized encoder instance.
+ * \param  write_callback     See FLAC__StreamEncoderWriteCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  seek_callback      See FLAC__StreamEncoderSeekCallback.  This
+ *                            pointer may be \c NULL if seeking is not
+ *                            supported.  The encoder uses seeking to go back
+ *                            and write some some stream statistics to the
+ *                            STREAMINFO block; this is recommended but not
+ *                            necessary to create a valid FLAC stream.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a tell_callback must also be supplied.
+ *                            Alternatively, a dummy seek callback that just
+ *                            returns \c FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  tell_callback      See FLAC__StreamEncoderTellCallback.  This
+ *                            pointer may be \c NULL if seeking is not
+ *                            supported.  If \a seek_callback is \c NULL then
+ *                            this argument will be ignored.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a tell_callback must also be supplied.
+ *                            Alternatively, a dummy tell callback that just
+ *                            returns \c FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  metadata_callback  See FLAC__StreamEncoderMetadataCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.  If the client provides a seek callback,
+ *                            this function is not necessary as the encoder
+ *                            will automatically seek back and update the
+ *                            STREAMINFO block.  It may also be \c NULL if the
+ *                            client does not support seeking, since it will
+ *                            have no way of going back to update the
+ *                            STREAMINFO.  However the client can still supply
+ *                            a callback if it would like to know the details
+ *                            from the STREAMINFO.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
  * \assert
  *    \code encoder != NULL \endcode
- * \retval FLAC__StreamEncoderState
- *    \c FLAC__STREAM_ENCODER_OK if initialization was successful; see
- *    FLAC__StreamEncoderState for the meanings of other return values.
+ * \retval FLAC__StreamEncoderInitStatus
+ *    \c FLAC__STREAM_ENCODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamEncoderInitStatus for the meanings of other return values.
+ */
+FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback write_callback, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderTellCallback tell_callback, FLAC__StreamEncoderMetadataCallback metadata_callback, void *client_data);
+
+/** Initialize the encoder instance.
+ *
+ *  This flavor of initialization sets up the encoder to encode to a plain
+ *  file.  For non-stdio streams, you must use
+ *  FLAC__stream_encoder_init_stream() and provide callbacks for the I/O.
+ *
+ *  This function should be called after FLAC__stream_encoder_new() and
+ *  FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process()
+ *  or FLAC__stream_encoder_process_interleaved().
+ *  initialization succeeded.
+ *
+ *  The call to FLAC__stream_encoder_init_stream() currently will also immediately
+ *  call the write callback several times, once with the \c fLaC signature,
+ *  and once for each encoded metadata block.
+ *
+ * \param  encoder            An uninitialized encoder instance.
+ * \param  file               An open file.  The file should have been opened
+ *                            with mode \c "w+b" and rewound.  The file
+ *                            becomes owned by the encoder and should not be
+ *                            manipulated by the client while encoding.
+ *                            Unless \a file is \c stdout, it will be closed
+ *                            when FLAC__stream_encoder_finish() is called.
+ *                            Note however that a proper SEEKTABLE cannot be
+ *                            created when encoding to \c stdout since it is
+ *                            not seekable.
+ * \param  progress_callback  See FLAC__StreamEncoderProgressCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code encoder != NULL \endcode
+ *    \code file != NULL \endcode
+ * \retval FLAC__StreamEncoderInitStatus
+ *    \c FLAC__STREAM_ENCODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamEncoderInitStatus for the meanings of other return values.
+ */
+FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_FILE(FLAC__StreamEncoder *encoder, FILE *file, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data);
+
+/** Initialize the encoder instance.
+ *
+ *  This flavor of initialization sets up the encoder to encode to a plain
+ *  file.  If POSIX fopen() semantics are not sufficient (for example,
+ *  with Unicode filenames on Windows), you must use
+ *  FLAC__stream_encodeR_init_FILE(), or FLAC__stream_encoder_init_stream()
+ *  and provide callbacks for the I/O.
+ *
+ *  This function should be called after FLAC__stream_encoder_new() and
+ *  FLAC__stream_encoder_set_*() but before FLAC__stream_encoder_process()
+ *  or FLAC__stream_encoder_process_interleaved().
+ *  initialization succeeded.
+ *
+ *  The call to FLAC__stream_encoder_init_stream() currently will also immediately
+ *  call the write callback several times, once with the \c fLaC signature,
+ *  and once for each encoded metadata block.
+ *
+ * \param  encoder            An uninitialized encoder instance.
+ * \param  filename           The name of the file to encode to.  The file will
+ *                            be opened with fopen().  Use \c NULL to encode to
+ *                            \c stdout.  Note however that a proper SEEKTABLE
+ *                            cannot be created when encoding to \c stdout since
+ *                            it is not seekable.
+ * \param  progress_callback  See FLAC__StreamEncoderProgressCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code encoder != NULL \endcode
+ * \retval FLAC__StreamEncoderInitStatus
+ *    \c FLAC__STREAM_ENCODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamEncoderInitStatus for the meanings of other return values.
  */
-FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder);
+FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(FLAC__StreamEncoder *encoder, const char *filename, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data);
 
 /** Finish the encoding process.
  *  Flushes the encoding buffer, releases resources, resets the encoder
index d776741..31b7e5f 100644 (file)
@@ -19,4 +19,4 @@ if FLaC__HAS_OGG
 OGGFLAC_DIRS = OggFLAC OggFLAC++
 endif
 
-SUBDIRS = FLAC FLAC++ $(OGGFLAC_DIRS) share
+SUBDIRS = FLAC FLAC++ $(OGGFLAC_DIRS) share test_libs_common
index 0be7bbd..94c6ae5 100644 (file)
@@ -34,8 +34,6 @@
 
 #include "export.h"
 
-#include "OggFLAC/file_decoder.h"
-#include "OggFLAC/seekable_stream_decoder.h"
 #include "OggFLAC/stream_decoder.h"
 // we only need this for the state abstraction really...
 #include "FLAC++/decoder.h"
  *  \ingroup oggflacpp
  *
  *  \brief
- *  This module describes the three decoder layers provided by libOggFLAC++.
+ *  This module describes the decoder layers provided by libOggFLAC++.
  *
  * The libOggFLAC++ decoder classes are object wrappers around their
- * counterparts in libOggFLAC.  All three decoding layers available in
+ * counterparts in libOggFLAC.  All decoding layers available in
  * libOggFLAC are also provided here.  The interface is very similar;
  * make sure to read the \link oggflac_decoder libOggFLAC decoder module \endlink.
  *
- * The only real difference here is that instead of passing in C function
- * pointers for callbacks, you inherit from the decoder class and provide
- * implementations for the callbacks in the derived class; because of this
- * there is no need for a 'client_data' property.
+ * There are only two significant differences here.  First, instead of
+ * passing in C function pointers for callbacks, you inherit from the
+ * decoder class and provide implementations for the callbacks in your
+ * derived class; because of this there is no need for a 'client_data'
+ * property.
+ *
+ * Second, there are two stream decoder classes.  OggFLAC::Decoder::Stream
+ * is used for the same cases that OggFLAC__stream_decoder_init_stream() is
+ * used, and OggFLAC::Decoder::File is used for the same cases that
+ * OggFLAC__stream_decoder_init_FILE() and OggFLAC__stream_decoder_init_file()
+ * are used.
  */
 
 namespace OggFLAC {
        namespace Decoder {
 
-               // ============================================================
-               //
-               //  Equivalent: OggFLAC__StreamDecoder
-               //
-               // ============================================================
-
                /** \defgroup oggflacpp_stream_decoder OggFLAC++/decoder.h: stream decoder class
                 *  \ingroup oggflacpp_decoder
                 *
                 *  \brief
                 *  This class wraps the ::OggFLAC__StreamDecoder.
                 *
-                * See the \link oggflac_stream_decoder libOggFLAC stream decoder module \endlink.
+                * See the \link oggflac_stream_decoder libOggFLAC stream decoder module \endlink
+                * for basic usage.
                 *
                 * \{
                 */
 
-               /** This class wraps the ::OggFLAC__StreamDecoder.
+               /** This class wraps the ::OggFLAC__StreamDecoder.  If you are
+                *  decoding from a file, OggFLAC::Decoder::File may be more
+                *  convenient.
+                *
+                * The usage of this class is similar to OggFLAC__StreamDecoder,
+                * except instead of providing callbacks to
+                * OggFLAC__stream_decoder_init_stream(), you will inherit from this
+                * class and override the virtual callback functions with your
+                * own implementations, then call Stream::init().  The rest of
+                * the calls work the same as in the C layer.
+                *
+                * Only the read, write, and error callbacks are mandatory.  The
+                * others are optional; this class provides default
+                * implementations that do nothing.  In order for seeking to work
+                * you must overide seek_callback(), tell_callback(),
+                * length_callback(), and eof_callback().
                 */
                class OggFLACPP_API Stream {
                public:
@@ -105,245 +120,150 @@ namespace OggFLAC {
                        Stream();
                        virtual ~Stream();
 
+                       /** Call after construction to check the that the object was created
+                        *  successfully.  If not, use get_state() to find out why not.
+                        *
+                        * \{
+                        */
                        bool is_valid() const;
                        inline operator bool() const { return is_valid(); }
-
-                       bool set_serial_number(long value);
-                       bool set_metadata_respond(::FLAC__MetadataType type);
-                       bool set_metadata_respond_application(const FLAC__byte id[4]);
-                       bool set_metadata_respond_all();
-                       bool set_metadata_ignore(::FLAC__MetadataType type);
-                       bool set_metadata_ignore_application(const FLAC__byte id[4]);
-                       bool set_metadata_ignore_all();
-
-                       State get_state() const;
-                       FLAC::Decoder::Stream::State get_FLAC_stream_decoder_state() const;
-                       unsigned get_channels() const;
-                       ::FLAC__ChannelAssignment get_channel_assignment() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
+                       /* \} */
+
+                       bool set_serial_number(long value);                            ///< See OggFLAC__stream_decoder_set_serial_number()
+                       bool set_md5_checking(bool value);                             ///< See OggFLAC__stream_decoder_set_md5_checking()
+                       bool set_metadata_respond(::FLAC__MetadataType type);          ///< See OggFLAC__stream_decoder_set_metadata_respond()
+                       bool set_metadata_respond_application(const FLAC__byte id[4]); ///< See OggFLAC__stream_decoder_set_metadata_respond_application()
+                       bool set_metadata_respond_all();                               ///< See OggFLAC__stream_decoder_set_metadata_respond_all()
+                       bool set_metadata_ignore(::FLAC__MetadataType type);           ///< See OggFLAC__stream_decoder_set_metadata_ignore()
+                       bool set_metadata_ignore_application(const FLAC__byte id[4]);  ///< See OggFLAC__stream_decoder_set_metadata_ignore_application()
+                       bool set_metadata_ignore_all();                                ///< See OggFLAC__stream_decoder_set_metadata_ignore_all()
+
+                       State get_state() const;                                  ///< See OggFLAC__stream_decoder_get_state()
+                       FLAC::Decoder::Stream::State get_FLAC_stream_decoder_state() const; ///< See OggFLAC__stream_decoder_get_FLAC_stream_decoder_state()
+                       bool get_md5_checking() const;                            ///< See OggFLAC__stream_decoder_get_md5_checking()
+                       FLAC__uint64 get_total_samples() const;                   ///< See OggFLAC__stream_decoder_get_total_samples()
+                       unsigned get_channels() const;                            ///< See OggFLAC__stream_decoder_get_channels()
+                       ::FLAC__ChannelAssignment get_channel_assignment() const; ///< See OggFLAC__stream_decoder_get_channel_assignment()
+                       unsigned get_bits_per_sample() const;                     ///< See OggFLAC__stream_decoder_get_bits_per_sample()
+                       unsigned get_sample_rate() const;                         ///< See OggFLAC__stream_decoder_get_sample_rate()
+                       unsigned get_blocksize() const;                           ///< See OggFLAC__stream_decoder_get_blocksize()
 
                        /** Initialize the instance; as with the C interface,
                         *  init() should be called after construction and 'set'
                         *  calls but before any of the 'process' calls.
+                        *
+                        *  See OggFLAC__stream_decoder_init_stream().
                         */
-                       State init();
+                       ::FLAC__StreamDecoderInitStatus init();
+
+                       void finish(); ///< See OggFLAC__stream_decoder_finish()
 
-                       void finish();
+                       bool flush(); ///< See OggFLAC__stream_decoder_flush()
+                       bool reset(); ///< See OggFLAC__stream_decoder_reset()
 
-                       bool flush();
-                       bool reset();
+                       bool process_single();                ///< See OggFLAC__stream_decoder_process_single()
+                       bool process_until_end_of_metadata(); ///< See OggFLAC__stream_decoder_process_until_end_of_metadata()
+                       bool process_until_end_of_stream();   ///< See OggFLAC__stream_decoder_process_until_end_of_stream()
+                       bool skip_single_frame();             ///< See OggFLAC__stream_decoder_skip_single_frame()
 
-                       bool process_single();
-                       bool process_until_end_of_metadata();
-                       bool process_until_end_of_stream();
+                       bool seek_absolute(FLAC__uint64 sample); ///< See OggFLAC__stream_decoder_seek_absolute()
                protected:
+                       /// see FLAC__StreamDecoderReadCallback
                        virtual ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 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;
-                       virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0;
-
-#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
-                       // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring()
-                       friend State;
-#endif
-                       ::OggFLAC__StreamDecoder *decoder_;
-               private:
-                       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);
-
-                       // Private and undefined so you can't use them:
-                       Stream(const Stream &);
-                       void operator=(const Stream &);
-               };
 
-               /* \} */
+                       /// see FLAC__StreamDecoderSeekCallback
+                       virtual ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
 
-               // ============================================================
-               //
-               //  Equivalent: OggFLAC__SeekableStreamDecoder
-               //
-               // ============================================================
+                       /// see FLAC__StreamDecoderTellCallback
+                       virtual ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
 
-               /** \defgroup oggflacpp_seekable_stream_decoder OggFLAC++/decoder.h: seekable stream decoder class
-                *  \ingroup oggflacpp_decoder
-                *
-                *  \brief
-                *  This class wraps the ::OggFLAC__SeekableStreamDecoder.
-                *
-                * See the \link oggflac_seekable_stream_decoder libOggFLAC seekable stream decoder module \endlink.
-                *
-                * \{
-                */
+                       /// see FLAC__StreamDecoderLengthCallback
+                       virtual ::FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length);
 
-               /** This class wraps the ::OggFLAC__SeekableStreamDecoder.
-                */
-               class OggFLACPP_API SeekableStream {
-               public:
-                       class OggFLACPP_API State {
-                       public:
-                               inline State(::OggFLAC__SeekableStreamDecoderState state): state_(state) { }
-                               inline operator ::OggFLAC__SeekableStreamDecoderState() const { return state_; }
-                               inline const char *as_cstring() const { return ::OggFLAC__SeekableStreamDecoderStateString[state_]; }
-                               inline const char *resolved_as_cstring(const SeekableStream &decoder) const { return ::OggFLAC__seekable_stream_decoder_get_resolved_state_string(decoder.decoder_); }
-                       protected:
-                               ::OggFLAC__SeekableStreamDecoderState state_;
-                       };
+                       /// see FLAC__StreamDecoderEofCallback
+                       virtual bool eof_callback();
 
-                       SeekableStream();
-                       virtual ~SeekableStream();
+                       /// see FLAC__StreamDecoderWriteCallback
+                       virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0;
 
-                       bool is_valid() const;
-                       inline operator bool() const { return is_valid(); }
+                       /// see FLAC__StreamDecoderMetadataCallback
+                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata);
 
-                       bool set_serial_number(long value);
-                       bool set_md5_checking(bool value);
-                       bool set_metadata_respond(::FLAC__MetadataType type);
-                       bool set_metadata_respond_application(const FLAC__byte id[4]);
-                       bool set_metadata_respond_all();
-                       bool set_metadata_ignore(::FLAC__MetadataType type);
-                       bool set_metadata_ignore_application(const FLAC__byte id[4]);
-                       bool set_metadata_ignore_all();
-
-                       State get_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;
-                       ::FLAC__ChannelAssignment get_channel_assignment() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-
-                       State init();
-
-                       bool finish();
-
-                       bool flush();
-                       bool reset();
-
-                       bool process_single();
-                       bool process_until_end_of_metadata();
-                       bool process_until_end_of_stream();
-
-                       bool seek_absolute(FLAC__uint64 sample);
-               protected:
-                       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;
+                       /// see FLAC__StreamDecoderErrorCallback
                        virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0;
 
 #if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
                        // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring()
                        friend State;
 #endif
-                       ::OggFLAC__SeekableStreamDecoder *decoder_;
-               private:
-                       static ::OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-                       static ::OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-                       static ::OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-                       static ::OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
-                       static FLAC__bool eof_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, void *client_data);
-                       static ::FLAC__StreamDecoderWriteStatus write_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-                       static void metadata_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
-                       static void error_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data);
+                       ::OggFLAC__StreamDecoder *decoder_;
 
+                       static ::FLAC__StreamDecoderReadStatus read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+                       static ::FLAC__StreamDecoderSeekStatus seek_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+                       static ::FLAC__StreamDecoderTellStatus tell_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+                       static ::FLAC__StreamDecoderLengthStatus length_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
+                       static FLAC__bool eof_callback_(const ::FLAC__StreamDecoder *decoder, void *client_data);
+                       static ::FLAC__StreamDecoderWriteStatus write_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+                       static void metadata_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
+                       static void error_callback_(const ::FLAC__StreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data);
+               private:
                        // Private and undefined so you can't use them:
-                       SeekableStream(const SeekableStream &);
-                       void operator=(const SeekableStream &);
+                       Stream(const Stream &);
+                       void operator=(const Stream &);
                };
 
                /* \} */
 
-               // ============================================================
-               //
-               //  Equivalent: OggFLAC__FileDecoder
-               //
-               // ============================================================
-
                /** \defgroup oggflacpp_file_decoder OggFLAC++/decoder.h: file decoder class
                 *  \ingroup oggflacpp_decoder
                 *
                 *  \brief
                 *  This class wraps the ::OggFLAC__FileDecoder.
                 *
-                * See the \link oggflac_file_decoder libOggFLAC file decoder module \endlink.
+                * See the \link oggflac_file_decoder libOggFLAC file decoder module \endlink
+                * for basic usage.
                 *
                 * \{
                 */
 
-               /** This class wraps the ::OggFLAC__FileDecoder.
+               /** This class wraps the ::OggFLAC__StreamDecoder.  If you are
+                *  not decoding from a file, you may need to use
+                *  OggFLAC::Decoder::Stream.
+                *
+                * The usage of this class is similar to OggFLAC__StreamDecoder,
+                * except instead of providing callbacks to
+                * OggFLAC__stream_decoder_init_FILE() or
+                * OggFLAC__stream_decoder_init_file(), you will inherit from this
+                * class and override the virtual callback functions with your
+                * own implementations, then call File::init().  The rest of
+                * the calls work the same as in the C layer.
+                *
+                * Only the write, and error callbacks from OggFLAC::Decoder::Stream
+                * are mandatory.  The others are optional; this class provides
+                * full working implementations for all other callbacks and
+                * supports seeking.
                 */
-               class OggFLACPP_API File {
+               class OggFLACPP_API File: public Stream {
                public:
-                       class OggFLACPP_API State {
-                       public:
-                               inline State(::OggFLAC__FileDecoderState state): state_(state) { }
-                               inline operator ::OggFLAC__FileDecoderState() const { return state_; }
-                               inline const char *as_cstring() const { return ::OggFLAC__FileDecoderStateString[state_]; }
-                               inline const char *resolved_as_cstring(const File &decoder) const { return ::OggFLAC__file_decoder_get_resolved_state_string(decoder.decoder_); }
-                       protected:
-                               ::OggFLAC__FileDecoderState state_;
-                       };
-
                        File();
                        virtual ~File();
 
-                       bool is_valid() const;
-                       inline operator bool() const { return is_valid(); }
-
-                       bool set_serial_number(long value);
-                       bool set_md5_checking(bool value);
-                       bool set_filename(const char *value); //!< 'value' may not be \c NULL; use "-" for stdin
-                       bool set_metadata_respond(::FLAC__MetadataType type);
-                       bool set_metadata_respond_application(const FLAC__byte id[4]);
-                       bool set_metadata_respond_all();
-                       bool set_metadata_ignore(::FLAC__MetadataType type);
-                       bool set_metadata_ignore_application(const FLAC__byte id[4]);
-                       bool set_metadata_ignore_all();
-
-                       State get_state() const;
-                       OggFLAC::Decoder::SeekableStream::State get_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;
-                       ::FLAC__ChannelAssignment get_channel_assignment() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-
-                       State init();
-
-                       bool finish();
-
-                       bool process_single();
-                       bool process_until_end_of_metadata();
-                       bool process_until_end_of_file();
-
-                       bool seek_absolute(FLAC__uint64 sample);
+                       /** Initialize the instance; as with the C interface,
+                        *  init() should be called after construction and 'set'
+                        *  calls but before any of the 'process' calls.
+                        *
+                        *  See OggFLAC__stream_decoder_init_FILE() and
+                        *  OggFLAC__stream_decoder_init_file().
+                        *  \{
+                        */
+                       ::FLAC__StreamDecoderInitStatus init(FILE *file);
+                       ::FLAC__StreamDecoderInitStatus init(const char *filename);
+                       ::FLAC__StreamDecoderInitStatus init(const std::string &filename);
+                       /*  \} */
                protected:
-                       virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) = 0;
-                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0;
-                       virtual void error_callback(::FLAC__StreamDecoderErrorStatus status) = 0;
-
-#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
-                       // lame hack: some MSVC/GCC versions can't see a protected decoder_ from nested State::resolved_as_cstring()
-                       friend State;
-#endif
-                       ::OggFLAC__FileDecoder *decoder_;
+                       // this is a dummy implementation to satisfy the pure virtual in Stream that is actually supplied internally by the C layer
+                       virtual ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
                private:
-                       static ::FLAC__StreamDecoderWriteStatus write_callback_(const ::OggFLAC__FileDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-                       static void metadata_callback_(const ::OggFLAC__FileDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
-                       static void error_callback_(const ::OggFLAC__FileDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data);
-
                        // Private and undefined so you can't use them:
                        File(const File &);
                        void operator=(const File &);
index 0c63937..5231ceb 100644 (file)
@@ -34,8 +34,6 @@
 
 #include "export.h"
 
-#include "OggFLAC/file_encoder.h"
-#include "OggFLAC/seekable_stream_encoder.h"
 #include "OggFLAC/stream_encoder.h"
 #include "decoder.h"
 // we only need these for the state abstractions really...
  *  \ingroup oggflacpp
  *
  *  \brief
- *  This module describes the three encoder layers provided by libOggFLAC++.
+ *  This module describes the encoder layers provided by libOggFLAC++.
  *
  * The libOggFLAC++ encoder classes are object wrappers around their
- * counterparts in libOggFLAC.  All three encoding layers available in
+ * counterparts in libOggFLAC.  All decoding layers available in
  * libOggFLAC are also provided here.  The interface is very similar;
  * make sure to read the \link oggflac_encoder libOggFLAC encoder module \endlink.
  *
- * The only real difference here is that instead of passing in C function
- * pointers for callbacks, you inherit from the encoder class and provide
- * implementations for the callbacks in the derived class; because of this
- * there is no need for a 'client_data' property.
+ * There are only two significant differences here.  First, instead of
+ * passing in C function pointers for callbacks, you inherit from the
+ * encoder class and provide implementations for the callbacks in your
+ * derived class; because of this there is no need for a 'client_data'
+ * property.
+ *
+ * Second, there are two stream encoder classes.  OggFLAC::Encoder::Stream
+ * is used for the same cases that OggFLAC__stream_encoder_init_stream() is
+ * used, and OggFLAC::Encoder::File is used for the same cases that
+ * OggFLAC__stream_encoder_init_FILE() and OggFLAC__stream_encoder_init_file()
+ * are used.
  */
 
 namespace OggFLAC {
        namespace Encoder {
 
-               // ============================================================
-               //
-               //  Equivalent: OggFLAC__StreamEncoder
-               //
-               // ============================================================
-
                /** \defgroup oggflacpp_stream_encoder OggFLAC++/encoder.h: stream encoder class
                 *  \ingroup oggflacpp_encoder
                 *
                 *  \brief
                 *  This class wraps the ::OggFLAC__StreamEncoder.
                 *
-                * See the \link oggflac_stream_encoder libOggFLAC stream encoder module \endlink.
+                * See the \link oggflac_stream_encoder libOggFLAC stream encoder module \endlink
+                * for basic usage.
                 *
                 * \{
                 */
 
-               /** This class wraps the ::OggFLAC__StreamEncoder.
+               /** This class wraps the ::OggFLAC__StreamEncoder.  If you are
+                *  encoding to a file, OggFLAC::Encoder::File may be more
+                *  convenient.
+                *
+                * The usage of this class is similar to OggFLAC__StreamEncoder,
+                * except instead of providing callbacks to
+                * OggFLAC__stream_encoder_init_stream(), you will inherit from this
+                * class and override the virtual callback functions with your
+                * own implementations, then call Stream::init().  The rest of
+                * the calls work the same as in the C layer.
+                *
+                * Only the write callback is mandatory.  The others are
+                * optional; this class provides default implementations that do
+                * nothing.  In order for some STREAMINFO and SEEKTABLE data to
+                * be written properly, you must overide read_callback(), seek_callback() and
+                * tell_callback(); see OggFLAC__stream_encoder_init_stream() as to
+                * why.
                 */
                class OggFLACPP_API Stream {
                public:
@@ -107,71 +123,99 @@ namespace OggFLAC {
                        Stream();
                        virtual ~Stream();
 
+                       /** Call after construction to check the that the object was created
+                        *  successfully.  If not, use get_state() to find out why not.
+                        *
+                        * \{
+                        */
                        bool is_valid() const;
                        inline operator bool() const { return is_valid(); }
+                       /* \} */
+
+                       bool set_serial_number(long value);                     ///< See OggFLAC__stream_encoder_set_serial_number()
+                       bool set_verify(bool value);                            ///< See OggFLAC__stream_encoder_set_verify()
+                       bool set_streamable_subset(bool value);                 ///< See OggFLAC__stream_encoder_set_streamable_subset()
+                       bool set_do_mid_side_stereo(bool value);                ///< See OggFLAC__stream_encoder_set_do_mid_side_stereo()
+                       bool set_loose_mid_side_stereo(bool value);             ///< See OggFLAC__stream_encoder_set_loose_mid_side_stereo()
+                       bool set_channels(unsigned value);                      ///< See OggFLAC__stream_encoder_set_channels()
+                       bool set_bits_per_sample(unsigned value);               ///< See OggFLAC__stream_encoder_set_bits_per_sample()
+                       bool set_sample_rate(unsigned value);                   ///< See OggFLAC__stream_encoder_set_sample_rate()
+                       bool set_blocksize(unsigned value);                     ///< See OggFLAC__stream_encoder_set_blocksize()
+                       bool set_apodization(const char *specification);        ///< See OggFLAC__stream_encoder_set_apodization()
+                       bool set_max_lpc_order(unsigned value);                 ///< See OggFLAC__stream_encoder_set_max_lpc_order()
+                       bool set_qlp_coeff_precision(unsigned value);           ///< See OggFLAC__stream_encoder_set_qlp_coeff_precision()
+                       bool set_do_qlp_coeff_prec_search(bool value);          ///< See OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search()
+                       bool set_do_escape_coding(bool value);                  ///< See OggFLAC__stream_encoder_set_do_escape_coding()
+                       bool set_do_exhaustive_model_search(bool value);        ///< See OggFLAC__stream_encoder_set_do_exhaustive_model_search()
+                       bool set_min_residual_partition_order(unsigned value);  ///< See OggFLAC__stream_encoder_set_min_residual_partition_order()
+                       bool set_max_residual_partition_order(unsigned value);  ///< See OggFLAC__stream_encoder_set_max_residual_partition_order()
+                       bool set_rice_parameter_search_dist(unsigned value);    ///< See OggFLAC__stream_encoder_set_rice_parameter_search_dist()
+                       bool set_total_samples_estimate(FLAC__uint64 value);    ///< See OggFLAC__stream_encoder_set_total_samples_estimate()
+                       bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks);     ///< See OggFLAC__stream_encoder_set_metadata()
+                       bool set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks); ///< See OggFLAC__stream_encoder_set_metadata()
+
+                       State    get_state() const;                                         ///< See OggFLAC__stream_encoder_get_state()
+                       FLAC::Encoder::Stream::State get_FLAC_stream_encoder_state() const; ///< See OggFLAC__stream_encoder_get_FLAC_stream_encoder_state()
+                       FLAC::Decoder::Stream::State get_verify_decoder_state() const;      ///< See OggFLAC__stream_encoder_get_verify_decoder_state()
+                       void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got); ///< See OggFLAC__stream_encoder_get_verify_decoder_error_stats()
+                       bool     get_verify() const;                       ///< See OggFLAC__stream_encoder_get_verify()
+                       bool     get_streamable_subset() const;            ///< See OggFLAC__stream_encoder_get_streamable_subset()
+                       bool     get_do_mid_side_stereo() const;           ///< See OggFLAC__stream_encoder_get_do_mid_side_stereo()
+                       bool     get_loose_mid_side_stereo() const;        ///< See OggFLAC__stream_encoder_get_loose_mid_side_stereo()
+                       unsigned get_channels() const;                     ///< See OggFLAC__stream_encoder_get_channels()
+                       unsigned get_bits_per_sample() const;              ///< See OggFLAC__stream_encoder_get_bits_per_sample()
+                       unsigned get_sample_rate() const;                  ///< See OggFLAC__stream_encoder_get_sample_rate()
+                       unsigned get_blocksize() const;                    ///< See OggFLAC__stream_encoder_get_blocksize()
+                       unsigned get_max_lpc_order() const;                ///< See OggFLAC__stream_encoder_get_max_lpc_order()
+                       unsigned get_qlp_coeff_precision() const;          ///< See OggFLAC__stream_encoder_get_qlp_coeff_precision()
+                       bool     get_do_qlp_coeff_prec_search() const;     ///< See OggFLAC__stream_encoder_get_do_qlp_coeff_prec_search()
+                       bool     get_do_escape_coding() const;             ///< See OggFLAC__stream_encoder_get_do_escape_coding()
+                       bool     get_do_exhaustive_model_search() const;   ///< See OggFLAC__stream_encoder_get_do_exhaustive_model_search()
+                       unsigned get_min_residual_partition_order() const; ///< See OggFLAC__stream_encoder_get_min_residual_partition_order()
+                       unsigned get_max_residual_partition_order() const; ///< See OggFLAC__stream_encoder_get_max_residual_partition_order()
+                       unsigned get_rice_parameter_search_dist() const;   ///< See OggFLAC__stream_encoder_get_rice_parameter_search_dist()
+                       FLAC__uint64 get_total_samples_estimate() const;   ///< See OggFLAC__stream_encoder_get_total_samples_estimate()
+
+                       /** Initialize the instance; as with the C interface,
+                        *  init() should be called after construction and 'set'
+                        *  calls but before any of the 'process' calls.
+                        *
+                        *  See OggFLAC__stream_encoder_init_stream().
+                        */
+                       ::FLAC__StreamEncoderInitStatus init();
+
+                       void finish(); ///< See OggFLAC__stream_encoder_finish()
+
+                       bool process(const FLAC__int32 * const buffer[], unsigned samples);     ///< See OggFLAC__stream_encoder_process()
+                       bool process_interleaved(const FLAC__int32 buffer[], unsigned samples); ///< See OggFLAC__stream_encoder_process_interleaved()
+               protected:
+                       /// See OggFLAC__StreamEncoderReadCallback
+                       virtual ::OggFLAC__StreamEncoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
 
-                       bool set_serial_number(long value);
-                       bool set_verify(bool value);
-                       bool set_streamable_subset(bool value);
-                       bool set_do_mid_side_stereo(bool value);
-                       bool set_loose_mid_side_stereo(bool value);
-                       bool set_channels(unsigned value);
-                       bool set_bits_per_sample(unsigned value);
-                       bool set_sample_rate(unsigned value);
-                       bool set_blocksize(unsigned value);
-                       bool set_apodization(const char *specification);
-                       bool set_max_lpc_order(unsigned value);
-                       bool set_qlp_coeff_precision(unsigned value);
-                       bool set_do_qlp_coeff_prec_search(bool value);
-                       bool set_do_escape_coding(bool value);
-                       bool set_do_exhaustive_model_search(bool value);
-                       bool set_min_residual_partition_order(unsigned value);
-                       bool set_max_residual_partition_order(unsigned value);
-                       bool set_rice_parameter_search_dist(unsigned value);
-                       bool set_total_samples_estimate(FLAC__uint64 value);
-                       bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks);
-
-                       State    get_state() const;
-                       FLAC::Encoder::Stream::State get_FLAC_stream_encoder_state() const;
-                       FLAC::Decoder::Stream::State get_verify_decoder_state() const;
-                       void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-                       bool     get_verify() const;
-                       bool     get_streamable_subset() const;
-                       bool     get_do_mid_side_stereo() const;
-                       bool     get_loose_mid_side_stereo() const;
-                       unsigned get_channels() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-                       unsigned get_max_lpc_order() const;
-                       unsigned get_qlp_coeff_precision() const;
-                       bool     get_do_qlp_coeff_prec_search() const;
-                       bool     get_do_escape_coding() const;
-                       bool     get_do_exhaustive_model_search() const;
-                       unsigned get_min_residual_partition_order() const;
-                       unsigned get_max_residual_partition_order() const;
-                       unsigned get_rice_parameter_search_dist() const;
-                       FLAC__uint64 get_total_samples_estimate() const;
+                       /// See FLAC__StreamEncoderWriteCallback
+                       virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame) = 0;
 
-                       State init();
+                       /// See FLAC__StreamEncoderSeekCallback
+                       virtual ::FLAC__StreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
 
-                       void finish();
+                       /// See FLAC__StreamEncoderTellCallback
+                       virtual ::FLAC__StreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
 
-                       bool process(const FLAC__int32 * const buffer[], unsigned samples);
-                       bool process_interleaved(const FLAC__int32 buffer[], unsigned samples);
-               protected:
-                       virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame) = 0;
-                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0;
+                       /// See FLAC__StreamEncoderTellCallback
+                       virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata);
 
 #if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
                        // lame hack: some MSVC/GCC versions can't see a protected encoder_ from nested State::resolved_as_cstring()
                        friend State;
 #endif
                        ::OggFLAC__StreamEncoder *encoder_;
-               private:
-                       static ::FLAC__StreamEncoderWriteStatus write_callback_(const ::OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-                       static void metadata_callback_(const ::OggFLAC__StreamEncoder *encoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
 
+                       static ::OggFLAC__StreamEncoderReadStatus read_callback_(const ::OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+                       static ::FLAC__StreamEncoderWriteStatus write_callback_(const ::FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
+                       static ::FLAC__StreamEncoderSeekStatus seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+                       static ::FLAC__StreamEncoderTellStatus tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+                       static void metadata_callback_(const ::FLAC__StreamEncoder *encoder, const ::FLAC__StreamMetadata *metadata, void *client_data);
+               private:
                        // Private and undefined so you can't use them:
                        Stream(const Stream &);
                        void operator=(const Stream &);
@@ -179,202 +223,61 @@ namespace OggFLAC {
 
                /* \} */
 
-               /** \defgroup oggflacpp_seekable_stream_encoder OggFLAC++/encoder.h: seekable stream encoder class
-                *  \ingroup oggflacpp_encoder
-                *
-                *  \brief
-                *  This class wraps the ::OggFLAC__SeekableStreamEncoder.
-                *
-                * See the \link oggflac_seekable_stream_encoder libOggFLAC seekable stream encoder module \endlink.
-                *
-                * \{
-                */
-
-               /** This class wraps the ::OggFLAC__SeekableStreamEncoder.
-                */
-               class OggFLACPP_API SeekableStream {
-               public:
-                       class OggFLACPP_API State {
-                       public:
-                               inline State(::OggFLAC__SeekableStreamEncoderState state): state_(state) { }
-                               inline operator ::OggFLAC__SeekableStreamEncoderState() const { return state_; }
-                               inline const char *as_cstring() const { return ::OggFLAC__SeekableStreamEncoderStateString[state_]; }
-                               inline const char *resolved_as_cstring(const SeekableStream &encoder) const { return ::OggFLAC__seekable_stream_encoder_get_resolved_state_string(encoder.encoder_); }
-                       protected:
-                               ::OggFLAC__SeekableStreamEncoderState state_;
-                       };
-
-                       SeekableStream();
-                       virtual ~SeekableStream();
-
-                       bool is_valid() const;
-                       inline operator bool() const { return is_valid(); }
-
-                       bool set_serial_number(long value);
-                       bool set_verify(bool value);
-                       bool set_streamable_subset(bool value);
-                       bool set_do_mid_side_stereo(bool value);
-                       bool set_loose_mid_side_stereo(bool value);
-                       bool set_channels(unsigned value);
-                       bool set_bits_per_sample(unsigned value);
-                       bool set_sample_rate(unsigned value);
-                       bool set_blocksize(unsigned value);
-                       bool set_apodization(const char *specification);
-                       bool set_max_lpc_order(unsigned value);
-                       bool set_qlp_coeff_precision(unsigned value);
-                       bool set_do_qlp_coeff_prec_search(bool value);
-                       bool set_do_escape_coding(bool value);
-                       bool set_do_exhaustive_model_search(bool value);
-                       bool set_min_residual_partition_order(unsigned value);
-                       bool set_max_residual_partition_order(unsigned value);
-                       bool set_rice_parameter_search_dist(unsigned value);
-                       bool set_total_samples_estimate(FLAC__uint64 value);
-                       bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks);
-
-                       State    get_state() const;
-                       FLAC::Encoder::Stream::State get_FLAC_stream_encoder_state() const;
-                       FLAC::Decoder::Stream::State get_verify_decoder_state() const;
-                       void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-                       bool     get_verify() const;
-                       bool     get_streamable_subset() const;
-                       bool     get_do_mid_side_stereo() const;
-                       bool     get_loose_mid_side_stereo() const;
-                       unsigned get_channels() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-                       unsigned get_max_lpc_order() const;
-                       unsigned get_qlp_coeff_precision() const;
-                       bool     get_do_qlp_coeff_prec_search() const;
-                       bool     get_do_escape_coding() const;
-                       bool     get_do_exhaustive_model_search() const;
-                       unsigned get_min_residual_partition_order() const;
-                       unsigned get_max_residual_partition_order() const;
-                       unsigned get_rice_parameter_search_dist() const;
-                       FLAC__uint64 get_total_samples_estimate() const;
-
-                       State init();
-
-                       void finish();
-
-                       bool process(const FLAC__int32 * const buffer[], unsigned samples);
-                       bool process_interleaved(const FLAC__int32 buffer[], unsigned samples);
-               protected:
-                       virtual ::OggFLAC__SeekableStreamEncoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes) = 0;
-                       virtual ::FLAC__SeekableStreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) = 0;
-                       virtual ::FLAC__SeekableStreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) = 0;
-                       virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame) = 0;
-
-#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
-                       // lame hack: some MSVC/GCC versions can't see a protected encoder_ from nested State::resolved_as_cstring()
-                       friend State;
-#endif
-                       ::OggFLAC__SeekableStreamEncoder *encoder_;
-               private:
-                       static ::OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-                       static ::FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-                       static ::FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-                       static ::FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-
-                       // Private and undefined so you can't use them:
-                       SeekableStream(const SeekableStream &);
-                       void operator=(const SeekableStream &);
-               };
-
-               /* \} */
-
                /** \defgroup oggflacpp_file_encoder OggFLAC++/encoder.h: file encoder class
                 *  \ingroup oggflacpp_encoder
                 *
                 *  \brief
                 *  This class wraps the ::OggFLAC__FileEncoder.
                 *
-                * See the \link oggflac_file_encoder libOggFLAC file encoder module \endlink.
+                * See the \link oggflac_file_encoder libOggFLAC file encoder module \endlink
+                * for basic usage.
                 *
                 * \{
                 */
 
-               /** This class wraps the ::OggFLAC__FileEncoder.
+               /** This class wraps the ::OggFLAC__StreamEncoder.  If you are
+                *  not encoding to a file, you may need to use
+                *  OggFLAC::Encoder::Stream.
+                *
+                * The usage of this class is similar to OggFLAC__StreamEncoder,
+                * except instead of providing callbacks to
+                * OggFLAC__stream_encoder_init_FILE() or
+                * OggFLAC__stream_encoder_init_file(), you will inherit from this
+                * class and override the virtual callback functions with your
+                * own implementations, then call File::init().  The rest of
+                * the calls work the same as in the C layer.
+                *
+                * There are no mandatory callbacks; all the callbacks from
+                * OggFLAC::Encoder::Stream are implemented here fully and support
+                * full post-encode STREAMINFO and SEEKTABLE updating.  There is
+                * only an optional progress callback which you may override to
+                * get periodic reports on the progress of the encode.
                 */
-               class OggFLACPP_API File {
+               class OggFLACPP_API File: public Stream {
                public:
-                       class OggFLACPP_API State {
-                       public:
-                               inline State(::OggFLAC__FileEncoderState state): state_(state) { }
-                               inline operator ::OggFLAC__FileEncoderState() const { return state_; }
-                               inline const char *as_cstring() const { return ::OggFLAC__FileEncoderStateString[state_]; }
-                               inline const char *resolved_as_cstring(const File &encoder) const { return ::OggFLAC__file_encoder_get_resolved_state_string(encoder.encoder_); }
-                       protected:
-                               ::OggFLAC__FileEncoderState state_;
-                       };
-
+                       /** Initialize the instance; as with the C interface,
+                        *  init() should be called after construction and 'set'
+                        *  calls but before any of the 'process' calls.
+                        *
+                        *  See OggFLAC__stream_encoder_init_FILE() and
+                        *  OggFLAC__stream_encoder_init_file().
+                        *  \{
+                        */
                        File();
                        virtual ~File();
+                       /*  \} */
 
-                       bool is_valid() const;
-                       inline operator bool() const { return is_valid(); }
-
-                       bool set_serial_number(long value);
-                       bool set_verify(bool value);
-                       bool set_streamable_subset(bool value);
-                       bool set_do_mid_side_stereo(bool value);
-                       bool set_loose_mid_side_stereo(bool value);
-                       bool set_channels(unsigned value);
-                       bool set_bits_per_sample(unsigned value);
-                       bool set_sample_rate(unsigned value);
-                       bool set_blocksize(unsigned value);
-                       bool set_apodization(const char *specification);
-                       bool set_max_lpc_order(unsigned value);
-                       bool set_qlp_coeff_precision(unsigned value);
-                       bool set_do_qlp_coeff_prec_search(bool value);
-                       bool set_do_escape_coding(bool value);
-                       bool set_do_exhaustive_model_search(bool value);
-                       bool set_min_residual_partition_order(unsigned value);
-                       bool set_max_residual_partition_order(unsigned value);
-                       bool set_rice_parameter_search_dist(unsigned value);
-                       bool set_total_samples_estimate(FLAC__uint64 value);
-                       bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks);
-                       bool set_filename(const char *value);
-
-                       State    get_state() const;
-                       SeekableStream::State get_seekable_stream_encoder_state() const;
-                       FLAC::Encoder::Stream::State get_FLAC_stream_encoder_state() const;
-                       FLAC::Decoder::Stream::State get_verify_decoder_state() const;
-                       void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-                       bool     get_verify() const;
-                       bool     get_streamable_subset() const;
-                       bool     get_do_mid_side_stereo() const;
-                       bool     get_loose_mid_side_stereo() const;
-                       unsigned get_channels() const;
-                       unsigned get_bits_per_sample() const;
-                       unsigned get_sample_rate() const;
-                       unsigned get_blocksize() const;
-                       unsigned get_max_lpc_order() const;
-                       unsigned get_qlp_coeff_precision() const;
-                       bool     get_do_qlp_coeff_prec_search() const;
-                       bool     get_do_escape_coding() const;
-                       bool     get_do_exhaustive_model_search() const;
-                       unsigned get_min_residual_partition_order() const;
-                       unsigned get_max_residual_partition_order() const;
-                       unsigned get_rice_parameter_search_dist() const;
-                       FLAC__uint64 get_total_samples_estimate() const;
-
-                       State init();
-
-                       void finish();
-
-                       bool process(const FLAC__int32 * const buffer[], unsigned samples);
-                       bool process_interleaved(const FLAC__int32 buffer[], unsigned samples);
+                       ::FLAC__StreamEncoderInitStatus init(FILE *file);
+                       ::FLAC__StreamEncoderInitStatus init(const char *filename);
+                       ::FLAC__StreamEncoderInitStatus init(const std::string &filename);
                protected:
+                       /// See FLAC__StreamEncoderProgressCallback
                        virtual void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate);
 
-#if (defined _MSC_VER) || (defined __GNUG__ && (__GNUG__ < 2 || (__GNUG__ == 2 && __GNUC_MINOR__ < 96))) || (defined __SUNPRO_CC)
-                       // lame hack: some MSVC/GCC versions can't see a protected encoder_ from nested State::resolved_as_cstring()
-                       friend State;
-#endif
-                       ::OggFLAC__FileEncoder *encoder_;
+                       /// This is a dummy implementation to satisfy the pure virtual in Stream that is actually supplied internally by the C layer
+                       virtual ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame);
                private:
-                       static void progress_callback_(const ::OggFLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
+                       static void progress_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
 
                        // Private and undefined so you can't use them:
                        File(const Stream &);
index f02b7ba..5c8e4df 100644 (file)
@@ -36,9 +36,5 @@ oggflaccincludedir = $(includedir)/OggFLAC
 oggflaccinclude_HEADERS = \
        all.h \
        export.h \
-       file_decoder.h \
-       file_encoder.h \
-       seekable_stream_decoder.h \
-       seekable_stream_encoder.h \
        stream_decoder.h \
        stream_encoder.h
index 7b647dd..d4080ed 100644 (file)
 
 #include "export.h"
 
-#include "file_decoder.h"
-#include "file_encoder.h"
-#include "seekable_stream_decoder.h"
-#include "seekable_stream_encoder.h"
 #include "stream_decoder.h"
 #include "stream_encoder.h"
 
diff --git a/include/OggFLAC/file_decoder.h b/include/OggFLAC/file_decoder.h
deleted file mode 100644 (file)
index 4942898..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef OggFLAC__FILE_DECODER_H
-#define OggFLAC__FILE_DECODER_H
-
-#include "export.h"
-
-#include "seekable_stream_decoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** \file include/OggFLAC/file_decoder.h
- *
- *  \brief
- *  This module contains the functions which implement the file
- *  decoder.
- *
- *  See the detailed documentation in the
- *  \link oggflac_file_decoder file decoder \endlink module.
- */
-
-/** \defgroup oggflac_file_decoder OggFLAC/file_decoder.h: file decoder interface
- *  \ingroup oggflac_decoder
- *
- *  \brief
- *  This module contains the functions which implement the file
- *  decoder.
- *
- * The interface here is nearly identical to FLAC's file decoder,
- * including the callbacks, with the addition of
- * OggFLAC__file_decoder_set_serial_number().  See the
- * \link flac_file_decoder FLAC file decoder module \endlink
- * for full documentation.
- *
- * \{
- */
-
-
-/** State values for an OggFLAC__FileDecoder
- *
- *  The decoder's state can be obtained by calling OggFLAC__file_decoder_get_state().
- */
-typedef enum {
-
-       OggFLAC__FILE_DECODER_OK = 0,
-       /**< The decoder is in the normal OK state. */
-
-       OggFLAC__FILE_DECODER_END_OF_FILE,
-       /**< The decoder has reached the end of the file. */
-
-       OggFLAC__FILE_DECODER_ERROR_OPENING_FILE,
-       /**< An error occurred opening the input file. */
-
-       OggFLAC__FILE_DECODER_SEEK_ERROR,
-       /**< An error occurred while seeking. */
-
-       OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR,
-       /**< An error occurred in the underlying seekable stream decoder;
-        * check OggFLAC__file_decoder_get_seekable_stream_decoder_state().
-        */
-
-       OggFLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
-
-       OggFLAC__FILE_DECODER_ALREADY_INITIALIZED,
-       /**< OggFLAC__file_decoder_init() was called when the decoder was
-        * already initialized, usually because
-        * OggFLAC__file_decoder_finish() was not called.
-        */
-
-       OggFLAC__FILE_DECODER_INVALID_CALLBACK,
-       /**< The decoder was initialized before setting all the required callbacks. */
-
-       OggFLAC__FILE_DECODER_UNINITIALIZED
-       /**< The decoder is in the uninitialized state. */
-
-} OggFLAC__FileDecoderState;
-
-/** Maps an OggFLAC__FileDecoderState to a C string.
- *
- *  Using an OggFLAC__FileDecoderState as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern OggFLAC_API const char * const OggFLAC__FileDecoderStateString[];
-
-
-/***********************************************************************
- *
- * class OggFLAC__FileDecoder : public OggFLAC__SeekableStreamDecoder
- *
- ***********************************************************************/
-
-struct OggFLAC__FileDecoderProtected;
-struct OggFLAC__FileDecoderPrivate;
-/** The opaque structure definition for the file decoder type.  See the
- *  \link oggflac_file_decoder file decoder module \endlink for a detailed
- *  description.
- */
-typedef struct {
-       struct OggFLAC__FileDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */
-       struct OggFLAC__FileDecoderPrivate *private_; /* avoid the C++ keyword 'private' */
-} OggFLAC__FileDecoder;
-
-/** Signature for the write callback.
- *  See OggFLAC__file_decoder_set_write_callback()
- *  and OggFLAC__SeekableStreamDecoderWriteCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  frame    The description of the decoded frame.
- * \param  buffer   An array of pointers to decoded channels of data.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__file_decoder_set_client_data().
- * \retval FLAC__StreamDecoderWriteStatus
- *    The callee's return status.
- */
-typedef FLAC__StreamDecoderWriteStatus (*OggFLAC__FileDecoderWriteCallback)(const OggFLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-
-/** Signature for the metadata callback.
- *  See OggFLAC__file_decoder_set_metadata_callback()
- *  and OggFLAC__SeekableStreamDecoderMetadataCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  metadata The decoded metadata block.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__file_decoder_set_client_data().
- */
-typedef void (*OggFLAC__FileDecoderMetadataCallback)(const OggFLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-
-/** Signature for the error callback.
- *  See OggFLAC__file_decoder_set_error_callback()
- *  and OggFLAC__SeekableStreamDecoderErrorCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  status   The error encountered by the decoder.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__file_decoder_set_client_data().
- */
-typedef void (*OggFLAC__FileDecoderErrorCallback)(const OggFLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-/** Create a new file decoder instance.  The instance is created with
- *  default settings; see the individual OggFLAC__file_decoder_set_*()
- *  functions for each setting's default.
- *
- * \retval OggFLAC__FileDecoder*
- *    \c NULL if there was an error allocating memory, else the new instance.
- */
-OggFLAC_API OggFLAC__FileDecoder *OggFLAC__file_decoder_new();
-
-/** Free a decoder instance.  Deletes the object pointed to by \a decoder.
- *
- * \param decoder  A pointer to an existing decoder.
- * \assert
- *    \code decoder != NULL \endcode
- */
-OggFLAC_API void OggFLAC__file_decoder_delete(OggFLAC__FileDecoder *decoder);
-
-
-/***********************************************************************
- *
- * Public class method prototypes
- *
- ***********************************************************************/
-
-/** Set the "MD5 signature checking" flag.
- *  This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_md5_checking().
- *
- * \default \c false
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_md5_checking(OggFLAC__FileDecoder *decoder, FLAC__bool value);
-
-/** Set the input file name to decode.
- *  This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_filename().
- *
- * \default \c "-"
- * \param  decoder  A decoder instance to set.
- * \param  value    The input file name, or "-" for \c stdin.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, or there was a memory
- *    allocation error, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_filename(OggFLAC__FileDecoder *decoder, const char *value);
-
-/** Set the write callback.
- *  This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_write_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_write_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderWriteCallback value);
-
-/** Set the metadata callback.
- *  This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_metadata_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderMetadataCallback value);
-
-/** Set the error callback.
- *  This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_error_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_error_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderErrorCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_client_data(OggFLAC__FileDecoder *decoder, void *value);
-
-/** Set the serial number for the Ogg stream.
- * The default behavior is to use the serial number of the first Ogg
- * page.  Setting a serial number here will explicitly specify which
- * stream is to be decoded.
- *
- * \default \c use serial number of first page
- * \param  decoder        A decoder instance to set.
- * \param  serial_number  See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_serial_number(OggFLAC__FileDecoder *decoder, long serial_number);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_metadata_respond().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  type     See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \a type is valid
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond(OggFLAC__FileDecoder *decoder, FLAC__MetadataType type);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_metadata_respond_application().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  id       See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code id != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond_application(OggFLAC__FileDecoder *decoder, const FLAC__byte id[4]);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_metadata_respond_all().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond_all(OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_metadata_ignore().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  type     See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \a type is valid
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore(OggFLAC__FileDecoder *decoder, FLAC__MetadataType type);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_metadata_ignore_application().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  id       See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code id != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore_application(OggFLAC__FileDecoder *decoder, const FLAC__byte id[4]);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_set_metadata_ignore_all().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore_all(OggFLAC__FileDecoder *decoder);
-
-/** Get the current decoder state.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval OggFLAC__FileDecoderState
- *    The current decoder state.
- */
-OggFLAC_API OggFLAC__FileDecoderState OggFLAC__file_decoder_get_state(const OggFLAC__FileDecoder *decoder);
-
-/** Get the state of the underlying seekable stream decoder.
- *  Useful when the file decoder state is
- *  \c OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__FileDecoderState
- *    The seekable stream decoder state.
- */
-OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_seekable_stream_decoder_state(const OggFLAC__FileDecoder *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_STREAM_DECODER_ERROR.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval OggFLAC__StreamDecoderState
- *    The stream decoder state.
- */
-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_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
- *    \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    The FLAC stream decoder state.
- */
-OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_decoder_get_FLAC_stream_decoder_state(const OggFLAC__FileDecoder *decoder);
-
-/** Get the current decoder state as a C string.
- *  This version automatically resolves
- *  \c OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR
- *  by getting the seekable stream decoder's state.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval const char *
- *    The decoder state as a C string.  Do not modify the contents.
- */
-OggFLAC_API const char *OggFLAC__file_decoder_get_resolved_state_string(const OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_get_md5_checking().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_get_md5_checking(const OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_get_channels().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-OggFLAC_API unsigned OggFLAC__file_decoder_get_channels(const OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_get_channel_assignment().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval OggFLAC__ChannelAssignment
- *    See above.
- */
-OggFLAC_API FLAC__ChannelAssignment OggFLAC__file_decoder_get_channel_assignment(const OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_get_bits_per_sample().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-OggFLAC_API unsigned OggFLAC__file_decoder_get_bits_per_sample(const OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_get_sample_rate().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-OggFLAC_API unsigned OggFLAC__file_decoder_get_sample_rate(const OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_get_blocksize().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDecoder *decoder);
-
-/** Initialize the decoder instance.
- *  Should be called after OggFLAC__file_decoder_new() and
- *  OggFLAC__file_decoder_set_*() but before any of the
- *  OggFLAC__file_decoder_process_*() functions.  Will set and return
- *  the decoder state, which will be OggFLAC__FILE_DECODER_OK if
- *  initialization succeeded.
- *
- * \param  decoder  An uninitialized decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval OggFLAC__FileDecoderState
- *    \c OggFLAC__FILE_DECODER_OK if initialization was successful; see
- *    OggFLAC__FileDecoderState for the meanings of other return values.
- */
-OggFLAC_API OggFLAC__FileDecoderState OggFLAC__file_decoder_init(OggFLAC__FileDecoder *decoder);
-
-/** Finish the decoding process.
- *  Flushes the decoding buffer, releases resources, resets the decoder
- *  settings to their defaults, and returns the decoder state to
- *  OggFLAC__FILE_DECODER_UNINITIALIZED.
- *
- *  In the event of a prematurely-terminated decode, it is not strictly
- *  necessary to call this immediately before OggFLAC__file_decoder_delete()
- *  but it is good practice to match every OggFLAC__file_decoder_init() with
- *  an OggFLAC__file_decoder_finish().
- *
- * \param  decoder  An uninitialized decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if MD5 checking is on AND a STREAMINFO block was available
- *    AND the MD5 signature in the STREAMINFO block was non-zero AND the
- *    signature does not match the one computed by the decoder; else
- *    \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_finish(OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_process_single().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_single(OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_process_until_end_of_metadata().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_metadata(OggFLAC__FileDecoder *decoder);
-
-/** This is inherited from FLAC__FileDecoder; see
- *  FLAC__file_decoder_process_until_end_of_stream().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_file(OggFLAC__FileDecoder *decoder);
-
-/** 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.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_seek_absolute(OggFLAC__FileDecoder *decoder, FLAC__uint64 sample);
-
-/* \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/OggFLAC/file_encoder.h b/include/OggFLAC/file_encoder.h
deleted file mode 100644 (file)
index c50e65b..0000000
+++ /dev/null
@@ -1,888 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef OggFLAC__FILE_ENCODER_H
-#define OggFLAC__FILE_ENCODER_H
-
-#include "export.h"
-#include "seekable_stream_encoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** \file include/OggFLAC/file_encoder.h
- *
- *  \brief
- *  This module contains the functions which implement the file
- *  encoder.
- *
- *  See the detailed documentation in the
- *  \link oggflac_file_encoder file encoder \endlink module.
- */
-
-/** \defgroup oggflac_file_encoder OggFLAC/file_encoder.h: file encoder interface
- *  \ingroup oggflac_encoder
- *
- *  \brief
- *  This module contains the functions which implement the file
- *  encoder.  Unlink the Ogg stream and seekable stream encoders, which
- *  derive from their FLAC counterparts, the Ogg file encoder is derived
- *  from the Ogg seekable stream encoder.
- *
- * The interface here is nearly identical to FLAC's file
- * encoder, including the callbacks, with the addition of
- * OggFLAC__file_encoder_set_serial_number().  See the
- * \link flac_file_encoder FLAC file encoder module \endlink
- * for full documentation.
- *
- * \{
- */
-
-
-/** State values for a OggFLAC__FileEncoder
- *
- *  The encoder's state can be obtained by calling OggFLAC__file_encoder_get_state().
- */
-typedef enum {
-
-       OggFLAC__FILE_ENCODER_OK = 0,
-       /**< The encoder is in the normal OK state. */
-
-       OggFLAC__FILE_ENCODER_NO_FILENAME,
-       /**< OggFLAC__file_encoder_init() was called without first calling
-        * OggFLAC__file_encoder_set_filename().
-        */
-
-       OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR,
-       /**< An error occurred in the underlying seekable stream encoder;
-        * check OggFLAC__file_encoder_get_seekable_stream_encoder_state().
-        */
-
-       OggFLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING,
-       /**< A fatal error occurred while writing to the encoded file. */
-
-       OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE,
-       /**< An error occurred opening the output file for writing. */
-
-       OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
-
-       OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED,
-       /**< OggFLAC__file_encoder_init() was called when the encoder was
-        * already initialized, usually because
-        * OggFLAC__file_encoder_finish() was not called.
-        */
-
-       OggFLAC__FILE_ENCODER_UNINITIALIZED
-       /**< The encoder is in the uninitialized state. */
-
-} OggFLAC__FileEncoderState;
-
-/** Maps a FLAC__FileEncoderState to a C string.
- *
- *  Using a FLAC__FileEncoderState as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern OggFLAC_API const char * const OggFLAC__FileEncoderStateString[];
-
-
-/***********************************************************************
- *
- * class FLAC__FileEncoder
- *
- ***********************************************************************/
-
-struct OggFLAC__FileEncoderProtected;
-struct OggFLAC__FileEncoderPrivate;
-/** The opaque structure definition for the file encoder type.
- *  See the \link oggflac_file_encoder file encoder module \endlink
- *  for a detailed description.
- */
-typedef struct {
-       struct OggFLAC__FileEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */
-       struct OggFLAC__FileEncoderPrivate *private_; /* avoid the C++ keyword 'private' */
-} OggFLAC__FileEncoder;
-
-/** Signature for the progress callback.
- *  See OggFLAC__file_encoder_set_progress_callback()
- *  and FLAC__FileEncoderProgressCallback for more info.
- *
- * \param  encoder          The encoder instance calling the callback.
- * \param  bytes_written    Bytes written so far.
- * \param  samples_written  Samples written so far.
- * \param  frames_written   Frames written so far.
- * \param  total_frames_estimate  The estimate of the total number of
- *                                frames to be written.
- * \param  client_data      The callee's client data set through
- *                          OggFLAC__file_encoder_set_client_data().
- */
-typedef void (*OggFLAC__FileEncoderProgressCallback)(const OggFLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-/** Create a new file encoder instance.  The instance is created with
- *  default settings; see the individual OggFLAC__file_encoder_set_*()
- *  functions for each setting's default.
- *
- * \retval OggFLAC__FileEncoder*
- *    \c NULL if there was an error allocating memory, else the new instance.
- */
-OggFLAC_API OggFLAC__FileEncoder *OggFLAC__file_encoder_new();
-
-/** Free an encoder instance.  Deletes the object pointed to by \a encoder.
- *
- * \param encoder  A pointer to an existing encoder.
- * \assert
- *    \code encoder != NULL \endcode
- */
-OggFLAC_API void OggFLAC__file_encoder_delete(OggFLAC__FileEncoder *encoder);
-
-/***********************************************************************
- *
- * Public class method prototypes
- *
- ***********************************************************************/
-
-/** Set the serial number for the FLAC stream.
- *
- * \default \c 0
- * \param  encoder        An encoder instance to set.
- * \param  serial_number  See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_serial_number(OggFLAC__FileEncoder *encoder, long serial_number);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_verify().
- *
- * \default \c true
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_verify(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_streamable_subset().
- *
- * \default \c true
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_streamable_subset(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_loose_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_channels().
- *
- * \default \c 2
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_channels(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_bits_per_sample().
- *
- * \warning
- * Do not feed the encoder data that is wider than the value you
- * set here or you will generate an invalid stream.
- *
- * \default \c 16
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_bits_per_sample(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_sample_rate().
- *
- * \default \c 44100
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_sample_rate(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_blocksize().
- *
- * \default \c 1152
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_blocksize(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_apodization().
- *
- * \default \c 0
- * \param  encoder        An encoder instance to set.
- * \param  specification  See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code specification != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_apodization(OggFLAC__FileEncoder *encoder, const char *specification);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_max_lpc_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_lpc_order(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision().
- *
- * \note
- * In the current implementation, qlp_coeff_precision + bits_per_sample must
- * be less than 32.
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_qlp_coeff_precision(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_do_escape_coding().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_escape_coding(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search().
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_exhaustive_model_search(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_min_residual_partition_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_min_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_max_residual_partition_order().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_rice_parameter_search_dist(OggFLAC__FileEncoder *encoder, unsigned value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_total_samples_estimate().
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_total_samples_estimate(OggFLAC__FileEncoder *encoder, FLAC__uint64 value);
-
-/** This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_set_metadata().
- *
- * \note The Ogg FLAC mapping requires that the VORBIS_COMMENT block be
- * the second metadata block of the stream.  The encoder already supplies
- * the STREAMINFO block automatically.  If \a metadata does not contain a
- * VORBIS_COMMENT block, the encoder will supply that too.  Otherwise, if
- * \a metadata does contain a VORBIS_COMMENT block and it is not the
- * first, this function will reorder \a metadata by moving the
- * VORBIS_COMMENT block to the front; the relative ordering of the other
- * blocks will remain as they were.
- *
- * \note The Ogg FLAC mapping limits the number of metadata blocks per
- * stream to \c 65535.  If \a num_blocks exceeds this the function will
- * return \c false.
- *
- * \default \c NULL, 0
- * \param  encoder     An encoder instance to set.
- * \param  metadata    See above.
- * \param  num_blocks  See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, or if
- *    \a num_blocks > 65535, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_metadata(OggFLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
-
-/** Set the output file name encode to.
- *
- * \note
- * The filename is mandatory and must be set before initialization.
- *
- * \note
- * Unlike the OggFLAC__FileDecoder, the filename does not interpret "-" for
- * \c stdout; writing to \c stdout is not relevant in the file encoder.
- *
- * \default \c NULL
- * \param  encoder  A encoder instance to set.
- * \param  value    The output file name.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, or there was a memory
- *    allocation error, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_filename(OggFLAC__FileEncoder *encoder, const char *value);
-
-/** Set the progress callback.
- *  The supplied function will be called when the encoder has finished
- *  writing a frame.  The \c total_frames_estimate argument to the callback
- *  will be based on the value from
- *  OggFLAC__file_encoder_set_total_samples_estimate().
- *
- * \note
- * Unlike most other callbacks, the progress callback is \b not mandatory
- * and need not be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_progress_callback(OggFLAC__FileEncoder *encoder, OggFLAC__FileEncoderProgressCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_client_data(OggFLAC__FileEncoder *encoder, void *value);
-
-/** Get the current encoder state.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__FileEncoderState
- *    The current encoder state.
- */
-OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_get_state(const OggFLAC__FileEncoder *encoder);
-
-/** Get the state of the underlying seekable stream encoder.
- *  Useful when the file encoder state is
- *  \c OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval OggFLAC__SeekableStreamEncoderState
- *    The seekable stream encoder state.
- */
-OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__file_encoder_get_seekable_stream_encoder_state(const OggFLAC__FileEncoder *encoder);
-
-/** Get the state of the underlying FLAC stream encoder.
- *  Useful when the file encoder state is
- *  \c OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR
- *  and the seekable stream encoder state is
- *  \c OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__StreamEncoderState
- *    The seekable stream encoder state.
- */
-OggFLAC_API FLAC__StreamEncoderState OggFLAC__file_encoder_get_FLAC_stream_encoder_state(const OggFLAC__FileEncoder *encoder);
-
-/** Get the state of the underlying stream encoder's verify decoder.
- *  Useful when the file encoder state is
- *  \c OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR
- *  and the seekable stream encoder state is
- *  \c OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR
- *  and the FLAC stream encoder state is
- *  \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    The stream encoder state.
- */
-OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_encoder_get_verify_decoder_state(const OggFLAC__FileEncoder *encoder);
-
-/** Get the current encoder state as a C string.
- *  This version automatically resolves
- *  \c OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR by getting the
- *  seekable stream encoder's state.
- *
- * \param  encoder  A encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval const char *
- *    The encoder state as a C string.  Do not modify the contents.
- */
-OggFLAC_API const char *OggFLAC__file_encoder_get_resolved_state_string(const OggFLAC__FileEncoder *encoder);
-
-/** Get relevant values about the nature of a verify decoder error.
- *  Inherited from OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats().
- *  Useful when the file encoder state is
- *  \c OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR
- *  and the seekable stream encoder state is
- *  \c OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_SEEKABLE_STREAM_ENCODER_ERROR
- *  and the FLAC seekable stream encoder state is
- *  \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR
- *  and the FLAC stream encoder state is
- *  \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \param  absolute_sample  The absolute sample number of the mismatch.
- * \param  frame_number  The number of the frame in which the mismatch occurred.
- * \param  channel       The channel in which the mismatch occurred.
- * \param  sample        The number of the sample (relative to the frame) in
- *                       which the mismatch occurred.
- * \param  expected      The expected value for the sample in question.
- * \param  got           The actual value returned by the decoder.
- * \assert
- *    \code encoder != NULL \endcode
- */
-OggFLAC_API void OggFLAC__file_encoder_get_verify_decoder_error_stats(const OggFLAC__FileEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-
-/** Get the "verify" flag.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_verify().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__file_encoder_set_verify().
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_verify(const OggFLAC__FileEncoder *encoder);
-
-/** Get the "streamable subset" flag.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_streamable_subset().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__file_encoder_set_streamable_subset().
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_streamable_subset(const OggFLAC__FileEncoder *encoder);
-
-/** Get the "mid/side stereo coding" flag.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__file_encoder_get_do_mid_side_stereo().
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_mid_side_stereo(const OggFLAC__FileEncoder *encoder);
-
-/** Get the "adaptive mid/side switching" flag.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__file_encoder_set_loose_mid_side_stereo().
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_loose_mid_side_stereo(const OggFLAC__FileEncoder *encoder);
-
-/** Get the number of input channels being processed.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_channels().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See FLAC__file_encoder_set_channels().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_channels(const OggFLAC__FileEncoder *encoder);
-
-/** Get the input sample resolution setting.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_bits_per_sample().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__file_encoder_set_bits_per_sample().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_bits_per_sample(const OggFLAC__FileEncoder *encoder);
-
-/** Get the input sample rate setting.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_sample_rate().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__file_encoder_set_sample_rate().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_sample_rate(const OggFLAC__FileEncoder *encoder);
-
-/** Get the blocksize setting.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_blocksize().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__file_encoder_set_blocksize().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_blocksize(const OggFLAC__FileEncoder *encoder);
-
-/** Get the maximum LPC order setting.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_max_lpc_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__file_encoder_set_max_lpc_order().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_max_lpc_order(const OggFLAC__FileEncoder *encoder);
-
-/** Get the quantized linear predictor coefficient precision setting.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__file_encoder_set_qlp_coeff_precision().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_qlp_coeff_precision(const OggFLAC__FileEncoder *encoder);
-
-/** Get the qlp coefficient precision search flag.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__file_encoder_set_do_qlp_coeff_prec_search().
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__FileEncoder *encoder);
-
-/** Get the "escape coding" flag.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_do_escape_coding().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__file_encoder_set_do_escape_coding().
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_escape_coding(const OggFLAC__FileEncoder *encoder);
-
-/** Get the exhaustive model search flag.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__file_encoder_set_do_exhaustive_model_search().
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_exhaustive_model_search(const OggFLAC__FileEncoder *encoder);
-
-/** Get the minimum residual partition order setting.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_min_residual_partition_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__file_encoder_set_min_residual_partition_order().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_min_residual_partition_order(const OggFLAC__FileEncoder *encoder);
-
-/** Get maximum residual partition order setting.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_max_residual_partition_order().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__file_encoder_set_max_residual_partition_order().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_max_residual_partition_order(const OggFLAC__FileEncoder *encoder);
-
-/** Get the Rice parameter search distance setting.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__file_encoder_set_rice_parameter_search_dist().
- */
-OggFLAC_API unsigned OggFLAC__file_encoder_get_rice_parameter_search_dist(const OggFLAC__FileEncoder *encoder);
-
-/** Get the previously set estimate of the total samples to be encoded.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_get_total_samples_estimate().
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__uint64
- *    See OggFLAC__file_encoder_set_total_samples_estimate().
- */
-OggFLAC_API FLAC__uint64 OggFLAC__file_encoder_get_total_samples_estimate(const OggFLAC__FileEncoder *encoder);
-
-/** Initialize the encoder instance.
- *  Should be called after OggFLAC__file_encoder_new() and
- *  OggFLAC__file_encoder_set_*() but before OggFLAC__file_encoder_process()
- *  or OggFLAC__file_encoder_process_interleaved().  Will set and return
- *  the encoder state, which will be OggFLAC__FILE_ENCODER_OK if
- *  initialization succeeded.
- *
- * \param  encoder  An uninitialized encoder instance.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval OggFLAC__FileEncoderState
- *    \c OggFLAC__FILE_ENCODER_OK if initialization was successful; see
- *    OggFLAC__FileEncoderState for the meanings of other return values.
- */
-OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_init(OggFLAC__FileEncoder *encoder);
-
-/** Finish the encoding process.
- *  Flushes the encoding buffer, releases resources, resets the encoder
- *  settings to their defaults, and returns the encoder state to
- *  OggFLAC__FILE_ENCODER_UNINITIALIZED.
- *
- *  In the event of a prematurely-terminated encode, it is not strictly
- *  necessary to call this immediately before OggFLAC__file_encoder_delete()
- *  but it is good practice to match every OggFLAC__file_encoder_init()
- *  with a OggFLAC__file_encoder_finish().
- *
- * \param  encoder  An uninitialized encoder instance.
- * \assert
- *    \code encoder != NULL \endcode
- */
-OggFLAC_API void OggFLAC__file_encoder_finish(OggFLAC__FileEncoder *encoder);
-
-/** Submit data for encoding.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_process().
- *
- * \param  encoder  An initialized encoder instance in the OK state.
- * \param  buffer   An array of pointers to each channel's signal.
- * \param  samples  The number of samples in one channel.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code OggFLAC__file_encoder_get_state(encoder) == OggFLAC__FILE_ENCODER_OK \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false; in this case, check the
- *    encoder state with OggFLAC__file_encoder_get_state() to see what
- *    went wrong.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_process(OggFLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples);
-
-/** Submit data for encoding.
- *  This is inherited from OggFLAC__SeekableStreamEncoder; see
- *  OggFLAC__seekable_stream_encoder_process_interleaved().
- *
- * \param  encoder  An initialized encoder instance in the OK state.
- * \param  buffer   An array of channel-interleaved data (see above).
- * \param  samples  The number of samples in one channel, the same as for
- *                  OggFLAC__file_encoder_process().  For example, if
- *                  encoding two channels, \c 1000 \a samples corresponds
- *                  to a \a buffer of 2000 values.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code OggFLAC__file_encoder_get_state(encoder) == OggFLAC__FILE_ENCODER_OK \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false; in this case, check the
- *    encoder state with OggFLAC__file_encoder_get_state() to see what
- *    went wrong.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_process_interleaved(OggFLAC__FileEncoder *encoder, const FLAC__int32 buffer[], unsigned samples);
-
-/* \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/OggFLAC/seekable_stream_decoder.h b/include/OggFLAC/seekable_stream_decoder.h
deleted file mode 100644 (file)
index b1fe3b9..0000000
+++ /dev/null
@@ -1,855 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef OggFLAC__SEEKABLE_STREAM_DECODER_H
-#define OggFLAC__SEEKABLE_STREAM_DECODER_H
-
-#include "export.h"
-#include "stream_decoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** \file include/OggFLAC/seekable_stream_decoder.h
- *
- *  \brief
- *  This module contains the functions which implement the seekable stream
- *  decoder.
- *
- *  See the detailed documentation in the
- *  \link oggflac_seekable_stream_decoder seekable stream decoder \endlink module.
- */
-
-/** \defgroup oggflac_seekable_stream_decoder OggFLAC/seekable_stream_decoder.h: seekable stream decoder interface
- *  \ingroup oggflac_decoder
- *
- *  \brief
- *  This module contains the functions which implement the seekable stream
- *  decoder.
- *
- * The interface here is nearly identical to FLAC's seekable stream decoder,
- * including the callbacks, with the addition of
- * OggFLAC__seekable_stream_decoder_set_serial_number().  See the
- * \link flac_seekable_stream_decoder FLAC seekable stream decoder module \endlink
- * for full documentation.
- *
- * \{
- */
-
-
-/** State values for an OggFLAC__SeekableStreamDecoder
- *
- *  The decoder's state can be obtained by calling OggFLAC__seekable_stream_decoder_get_state().
- */
-typedef enum {
-
-       OggFLAC__SEEKABLE_STREAM_DECODER_OK = 0,
-       /**< The decoder is in the normal OK state. */
-
-       OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING,
-       /**< The decoder is in the process of seeking. */
-
-       OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM,
-       /**< The decoder has reached the end of the stream. */
-
-       OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
-
-       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_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
-        * already initialized, usually because
-        * OggFLAC__seekable_stream_decoder_finish() was not called.
-        */
-
-       OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK,
-       /**< The decoder was initialized before setting all the required callbacks. */
-
-       OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED
-       /**< The decoder is in the uninitialized state. */
-
-} OggFLAC__SeekableStreamDecoderState;
-
-/** Maps an OggFLAC__SeekableStreamDecoderState to a C string.
- *
- *  Using an OggFLAC__SeekableStreamDecoderState as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-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
- *
- ***********************************************************************/
-
-struct OggFLAC__SeekableStreamDecoderProtected;
-struct OggFLAC__SeekableStreamDecoderPrivate;
-/** The opaque structure definition for the seekable stream decoder type.
- *  See the
- *  \link oggflac_seekable_stream_decoder seekable stream decoder module \endlink
- *  for a detailed description.
- */
-typedef struct {
-       struct OggFLAC__SeekableStreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */
-       struct OggFLAC__SeekableStreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */
-} OggFLAC__SeekableStreamDecoder;
-
-/** Signature for the read callback.
- *  See OggFLAC__seekable_stream_decoder_set_read_callback()
- *  and OggFLAC__StreamDecoderReadCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  buffer   A pointer to a location for the callee to store
- *                  data to be decoded.
- * \param  bytes    A pointer to the size of the buffer.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__SeekableStreamDecoderReadStatus
- *    The callee's return status.
- */
-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.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  absolute_byte_offset  The offset from the beginning of the stream
- *                               to seek to.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__SeekableStreamDecoderSeekStatus
- *    The callee's return status.
- */
-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.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  absolute_byte_offset  A pointer to storage for the current offset
- *                               from the beginning of the stream.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__SeekableStreamDecoderTellStatus
- *    The callee's return status.
- */
-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.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  stream_length  A pointer to storage for the length of the stream
- *                        in bytes.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__SeekableStreamDecoderLengthStatus
- *    The callee's return status.
- */
-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.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__bool
- *    \c true if the currently at the end of the stream, else \c false.
- */
-typedef FLAC__bool (*OggFLAC__SeekableStreamDecoderEofCallback)(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data);
-
-/** Signature for the write callback.
- *  See OggFLAC__seekable_stream_decoder_set_write_callback()
- *  and OggFLAC__StreamDecoderWriteCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  frame    The description of the decoded frame.
- * \param  buffer   An array of pointers to decoded channels of data.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_decoder_set_client_data().
- * \retval FLAC__StreamDecoderWriteStatus
- *    The callee's return status.
- */
-typedef FLAC__StreamDecoderWriteStatus (*OggFLAC__SeekableStreamDecoderWriteCallback)(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-
-/** Signature for the metadata callback.
- *  See OggFLAC__seekable_stream_decoder_set_metadata_callback()
- *  and OggFLAC__StreamDecoderMetadataCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  metadata The decoded metadata block.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_decoder_set_client_data().
- */
-typedef void (*OggFLAC__SeekableStreamDecoderMetadataCallback)(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-
-/** Signature for the error callback.
- *  See OggFLAC__seekable_stream_decoder_set_error_callback()
- *  and OggFLAC__StreamDecoderErrorCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  status   The error encountered by the decoder.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_decoder_set_client_data().
- */
-typedef void (*OggFLAC__SeekableStreamDecoderErrorCallback)(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-/** Create a new seekable stream decoder instance.  The instance is created
- *  with default settings; see the individual
- *  OggFLAC__seekable_stream_decoder_set_*() functions for each setting's
- *  default.
- *
- * \retval OggFLAC__SeekableStreamDecoder*
- *    \c NULL if there was an error allocating memory, else the new instance.
- */
-OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new();
-
-/** Free a decoder instance.  Deletes the object pointed to by \a decoder.
- *
- * \param decoder  A pointer to an existing decoder.
- * \assert
- *    \code decoder != NULL \endcode
- */
-OggFLAC_API void OggFLAC__seekable_stream_decoder_delete(OggFLAC__SeekableStreamDecoder *decoder);
-
-
-/***********************************************************************
- *
- * Public class method prototypes
- *
- ***********************************************************************/
-
-/** Set the "MD5 signature checking" flag.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_md5_checking().
- *
- * \default \c false
- * \param  decoder  A decoder instance to set.
- * \param  value    Flag value (see above).
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_md5_checking(OggFLAC__SeekableStreamDecoder *decoder, FLAC__bool value);
-
-/** Set the read callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_read_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_read_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderReadCallback value);
-
-/** Set the seek callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_seek_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_seek_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderSeekCallback value);
-
-/** Set the tell callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_tell_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_tell_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderTellCallback value);
-
-/** Set the length callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_length_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_length_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderLengthCallback value);
-
-/** Set the eof callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_eof_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_eof_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderEofCallback value);
-
-/** Set the write callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_write_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_write_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderWriteCallback value);
-
-/** Set the metadata callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderMetadataCallback value);
-
-/** Set the error callback.
- *  This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_error_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_error_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderErrorCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_client_data(OggFLAC__SeekableStreamDecoder *decoder, void *value);
-
-/** Set the serial number for the Ogg stream.
- * The default behavior is to use the serial number of the first Ogg
- * page.  Setting a serial number here will explicitly specify which
- * stream is to be decoded.
- *
- * \default \c use serial number of first page
- * \param  decoder        A decoder instance to set.
- * \param  serial_number  See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_serial_number(OggFLAC__SeekableStreamDecoder *decoder, long serial_number);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_respond().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  type     See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \a type is valid
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_respond_application().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  id       See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code id != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4]);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_respond_all().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_ignore().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  type     See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \a type is valid
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_ignore_application().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \param  id       See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code id != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4]);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_set_metadata_ignore_all().
- *
- * \default By default, only the \c STREAMINFO block is returned via the
- *          metadata callback.
- * \param  decoder  A decoder instance to set.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** Get the current decoder state.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval OggFLAC__SeekableStreamDecoderState
- *    The current decoder state.
- */
-OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** Get the state of the underlying stream decoder.
- *  Useful when the seekable stream decoder state is
- *  \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval OggFLAC__StreamDecoderState
- *    The stream decoder state.
- */
-OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *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_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
- *    \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    The FLAC stream decoder state.
- */
-OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** Get the current decoder state as a C string.
- *  This version automatically resolves
- *  \c OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR
- *  by getting the stream decoder's state.
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval const char *
- *    The decoder state as a C string.  Do not modify the contents.
- */
-OggFLAC_API const char *OggFLAC__seekable_stream_decoder_get_resolved_state_string(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_md5_checking().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_md5_checking(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_channels().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_channels(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_channel_assignment().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval OggFLAC__ChannelAssignment
- *    See above.
- */
-OggFLAC_API FLAC__ChannelAssignment OggFLAC__seekable_stream_decoder_get_channel_assignment(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_bits_per_sample().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_bits_per_sample(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_sample_rate().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_get_blocksize().
- *
- * \param  decoder  A decoder instance to query.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval unsigned
- *    See above.
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder);
-
-/** Initialize the decoder instance.
- *  Should be called after OggFLAC__seekable_stream_decoder_new() and
- *  OggFLAC__seekable_stream_decoder_set_*() but before any of the
- *  OggFLAC__seekable_stream_decoder_process_*() functions.  Will set and return
- *  the decoder state, which will be OggFLAC__SEEKABLE_STREAM_DECODER_OK
- *  if initialization succeeded.
- *
- * \param  decoder  An uninitialized decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval OggFLAC__SeekableStreamDecoderState
- *    \c OggFLAC__SEEKABLE_STREAM_DECODER_OK if initialization was
- *    successful; see OggFLAC__SeekableStreamDecoderState for the meanings
- *    of other return values.
- */
-OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_init(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** Finish the decoding process.
- *  Flushes the decoding buffer, releases resources, resets the decoder
- *  settings to their defaults, and returns the decoder state to
- *  OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED.
- *
- *  In the event of a prematurely-terminated decode, it is not strictly
- *  necessary to call this immediately before
- *  OggFLAC__seekable_stream_decoder_delete() but it is good practice to match
- *  every OggFLAC__seekable_stream_decoder_init() with a
- *  OggFLAC__seekable_stream_decoder_finish().
- *
- * \param  decoder  An uninitialized decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if MD5 checking is on AND a STREAMINFO block was available
- *    AND the MD5 signature in the STREAMINFO block was non-zero AND the
- *    signature does not match the one computed by the decoder; else
- *    \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_flush().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false if a memory allocation
- *    or stream decoder error occurs.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_reset().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false if a memory allocation
- *    or stream decoder error occurs.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_reset(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_process_single().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_process_until_end_of_metadata().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_process_until_end_of_stream().
- *
- * \param  decoder  A decoder instance.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    See above.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_stream(OggFLAC__SeekableStreamDecoder *decoder);
-
-/** This is inherited from FLAC__SeekableStreamDecoder; see
- *  FLAC__seekable_stream_decoder_seek_absolute().
- *
- * \param  decoder  A decoder instance.
- * \param  sample   The target sample number to seek to.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_seek_absolute(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample);
-
-/* \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/OggFLAC/seekable_stream_encoder.h b/include/OggFLAC/seekable_stream_encoder.h
deleted file mode 100644 (file)
index f317800..0000000
+++ /dev/null
@@ -1,949 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006 Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef OggFLAC__SEEKABLE_STREAM_ENCODER_H
-#define OggFLAC__SEEKABLE_STREAM_ENCODER_H
-
-#include "export.h"
-
-#include "FLAC/stream_encoder.h"
-#include "FLAC/seekable_stream_encoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** \file include/OggFLAC/seekable_stream_encoder.h
- *
- *  \brief
- *  This module contains the functions which implement the seekable
- *  stream encoder.
- *
- *  See the detailed documentation in the
- *  \link oggflac_seekable_stream_encoder seekable stream encoder \endlink module.
- */
-
-/** \defgroup oggflac_seekable_stream_encoder OggFLAC/seekable_stream_encoder.h: seekable stream encoder interface
- *  \ingroup oggflac_encoder
- *
- *  \brief
- *  This module contains the functions which implement the seekable
- *  stream encoder.  The Ogg seekable stream encoder is derived
- *  from the FLAC seekable stream encoder.
- *
- * The interface here is nearly identical to FLAC's seekable stream
- * encoder, including the callbacks, with the addition of a new required
- * read callback (needed when writing back STREAMINFO after encoding) and
- * OggFLAC__seekable_stream_encoder_set_serial_number().  See the
- * \link flac_seekable_stream_encoder FLAC seekable stream encoder module \endlink
- * for full documentation.
- *
- * \{
- */
-
-
-/** State values for an OggFLAC__SeekableStreamEncoder
- *
- *  The encoder's state can be obtained by calling OggFLAC__stream_encoder_get_state().
- */
-typedef enum {
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_OK = 0,
-       /**< The encoder is in the normal OK state. */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR,
-       /**< An error occurred in the underlying Ogg layer.  */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR,
-       /**< An error occurred in the underlying FLAC stream encoder;
-        * check OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state().
-        */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR,
-       /**< The write callback returned an error. */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR,
-       /**< The read callback returned an error. */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR,
-       /**< The seek callback returned an error. */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR,
-       /**< The tell callback returned an error. */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED,
-       /**< OggFLAC__seekable_stream_encoder_init() was called when the encoder was
-        * already initialized, usually because
-        * OggFLAC__seekable_stream_encoder_finish() was not called.
-        */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK,
-       /**< OggFLAC__seekable_stream_encoder_init() was called without all
-        * callbacks being set.
-        */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE,
-       /**< An invalid seek table was passed is the metadata to
-        * OggFLAC__seekable_stream_encoder_set_metadata().
-        */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED
-       /**< The encoder is in the uninitialized state. */
-
-} OggFLAC__SeekableStreamEncoderState;
-
-/** Maps an OggFLAC__StreamEncoderState to a C string.
- *
- *  Using an OggFLAC__StreamEncoderState as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderStateString[];
-
-
-/** Return values for the OggFLAC__SeekableStreamEncoder read callback.
- */
-typedef enum {
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE,
-       /**< The read was OK and decoding can continue. */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM,
-       /**< The read was attempted at the end of the stream. */
-
-       OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT
-       /**< An unrecoverable error occurred. */
-
-} OggFLAC__SeekableStreamEncoderReadStatus;
-
-/** Maps a OggFLAC__SeekableStreamEncoderReadStatus to a C string.
- *
- *  Using a OggFLAC__SeekableStreamEncoderReadStatus as the index to this array
- *  will give the string equivalent.  The contents should not be modified.
- */
-extern OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderReadStatusString[];
-
-
-/***********************************************************************
- *
- * class OggFLAC__StreamEncoder
- *
- ***********************************************************************/
-
-struct OggFLAC__SeekableStreamEncoderProtected;
-struct OggFLAC__SeekableStreamEncoderPrivate;
-/** The opaque structure definition for the seekable stream encoder type.
- *  See the \link oggflac_seekable_stream_encoder seekable stream encoder module \endlink
- *  for a detailed description.
- */
-typedef struct {
-       struct OggFLAC__SeekableStreamEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */
-       struct OggFLAC__SeekableStreamEncoderPrivate *private_; /* avoid the C++ keyword 'private' */
-} OggFLAC__SeekableStreamEncoder;
-
-/** Signature for the read callback.
- *  See OggFLAC__seekable_stream_encoder_set_read_callback() for more info.
- *
- * \param  encoder  The encoder instance calling the callback.
- * \param  buffer   A pointer to a location for the callee to store
- *                  data to be encoded.
- * \param  bytes    A pointer to the size of the buffer.  On entry
- *                  to the callback, it contains the maximum number
- *                  of bytes that may be stored in \a buffer.  The
- *                  callee must set it to the actual number of bytes
- *                  stored (0 in case of error or end-of-stream) before
- *                  returning.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_encoder_set_client_data().
- * \retval OggFLAC__SeekableStreamEncoderReadStatus
- *    The callee's return status.
- */
-typedef OggFLAC__SeekableStreamEncoderReadStatus (*OggFLAC__SeekableStreamEncoderReadCallback)(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-
-/** Signature for the seek callback.
- *  See OggFLAC__seekable_stream_encoder_set_seek_callback()
- *  and FLAC__SeekableStreamEncoderSeekCallback for more info.
- *
- * \param  encoder  The encoder instance calling the callback.
- * \param  absolute_byte_offset  The offset from the beginning of the stream
- *                               to seek to.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_encoder_set_client_data().
- * \retval FLAC__SeekableStreamEncoderSeekStatus
- *    The callee's return status.
- */
-typedef FLAC__SeekableStreamEncoderSeekStatus (*OggFLAC__SeekableStreamEncoderSeekCallback)(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-
-/** Signature for the tell callback.
- *  See OggFLAC__seekable_stream_encoder_set_tell_callback()
- *  and FLAC__SeekableStreamEncoderTellCallback for more info.
- *
- * \param  encoder  The encoder instance calling the callback.
- * \param  absolute_byte_offset  The address at which to store the current
- *                               position of the output.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_encoder_set_client_data().
- * \retval FLAC__SeekableStreamEncoderTellStatus
- *    The callee's return status.
- */
-typedef FLAC__SeekableStreamEncoderTellStatus (*OggFLAC__SeekableStreamEncoderTellCallback)(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-
-/** Signature for the write callback.
- *  See OggFLAC__seekable_stream_encoder_set_write_callback()
- *  and FLAC__SeekableStreamEncoderWriteCallback for more info.
- *
- * \param  encoder  The encoder instance calling the callback.
- * \param  buffer   An array of encoded data of length \a bytes.
- * \param  bytes    The byte length of \a buffer.
- * \param  samples  The number of samples encoded by \a buffer.
- *                  \c 0 has a special meaning; see
- *                  OggFLAC__seekable_stream_encoder_set_write_callback().
- * \param  current_frame  The number of current frame being encoded.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__seekable_stream_encoder_set_client_data().
- * \retval FLAC__StreamEncoderWriteStatus
- *    The callee's return status.
- */
-typedef FLAC__StreamEncoderWriteStatus (*OggFLAC__SeekableStreamEncoderWriteCallback)(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-/** Create a new seekable stream encoder instance.  The instance is created with
- *  default settings; see the individual OggFLAC__seekable_stream_encoder_set_*()
- *  functions for each setting's default.
- *
- * \retval OggFLAC__SeekableStreamEncoder*
- *    \c NULL if there was an error allocating memory, else the new instance.
- */
-OggFLAC_API OggFLAC__SeekableStreamEncoder *OggFLAC__seekable_stream_encoder_new();
-
-/** Free an encoder instance.  Deletes the object pointed to by \a encoder.
- *
- * \param encoder  A pointer to an existing encoder.
- * \assert
- *    \code encoder != NULL \endcode
- */
-OggFLAC_API void OggFLAC__seekable_stream_encoder_delete(OggFLAC__SeekableStreamEncoder *encoder);
-
-
-/***********************************************************************
- *
- * Public class method prototypes
- *
- ***********************************************************************/
-
-/** Set the serial number for the FLAC stream.
- *
- * \default \c 0
- * \param  encoder        An encoder instance to set.
- * \param  serial_number  See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_serial_number(OggFLAC__SeekableStreamEncoder *encoder, long serial_number);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_verify()
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    Flag value (see above).
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_verify(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_streamable_subset()
- *
- * \default \c true
- * \param  encoder  An encoder instance to set.
- * \param  value    Flag value (see above).
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_streamable_subset(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_do_mid_side_stereo()
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    Flag value (see above).
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_loose_mid_side_stereo()
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    Flag value (see above).
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_channels()
- *
- * \default \c 2
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_channels(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_bits_per_sample()
- *
- * \default \c 16
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_bits_per_sample(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_sample_rate()
- *
- * \default \c 44100
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_sample_rate(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_blocksize()
- *
- * \default \c 1152
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_blocksize(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_apodization()
- *
- * \default \c 0
- * \param  encoder        An encoder instance to set.
- * \param  specification  See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code specification != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_apodization(OggFLAC__SeekableStreamEncoder *encoder, const char *specification);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_max_lpc_order()
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_lpc_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_qlp_coeff_precision()
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_qlp_coeff_prec_search()
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_do_escape_coding()
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_escape_coding(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_do_exhaustive_model_search()
- *
- * \default \c false
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_min_residual_partition_order()
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_max_residual_partition_order()
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_rice_parameter_search_dist()
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(OggFLAC__SeekableStreamEncoder *encoder, unsigned value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_total_samples_estimate()
- *
- * \default \c 0
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_total_samples_estimate(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 value);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_metadata()
- *
- * \note The Ogg FLAC mapping requires that the VORBIS_COMMENT block be
- * the second metadata block of the stream.  The encoder already supplies
- * the STREAMINFO block automatically.  If \a metadata does not contain a
- * VORBIS_COMMENT block, the encoder will supply that too.  Otherwise, if
- * \a metadata does contain a VORBIS_COMMENT block and it is not the
- * first, this function will reorder \a metadata by moving the
- * VORBIS_COMMENT block to the front; the relative ordering of the other
- * blocks will remain as they were.
- *
- * \note The Ogg FLAC mapping limits the number of metadata blocks per
- * stream to \c 65535.  If \a num_blocks exceeds this the function will
- * return \c false.
- *
- * \default \c NULL, 0
- * \param  encoder     An encoder instance to set.
- * \param  metadata    See above.
- * \param  num_blocks  See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, or if
- *    \a num_blocks > 65535, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
-
-/** Set the read callback.
- *  The supplied function will be called when the encoder needs to read back
- *  encoded data.  This happens during the metadata callback, when the encoder
- *  has to read, modify, and rewrite the metadata (e.g. seekpoints) gathered
- *  while encoding.  The address of the buffer to be filled is supplied, along
- *  with the number of bytes the buffer can hold.  The callback may choose to
- *  supply less data and modify the byte count but must be careful not to
- *  overflow the buffer.  The callback then returns a status code chosen from
- *  OggFLAC__SeekableStreamEncoderReadStatus.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  A encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_read_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderReadCallback value);
-
-/** Set the seek callback.
- *  The supplied function will be called when the encoder needs to seek
- *  the output stream.  The encoder will pass the absolute byte offset
- *  to seek to, 0 meaning the beginning of the stream.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_seek_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderSeekCallback value);
-
-/** Set the tell callback.
- *  The supplied function will be called when the encoder needs to know
- *  the current position of the output stream.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_tell_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderTellCallback value);
-
-/** Set the write callback.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_write_callback().
- *
- * \note
- * Unlike the FLAC seekable stream encoder write callback, the Ogg
- * seekable stream encoder write callback will be called twice when
- * writing audio frames; once for the page header, and once for the page
- * body.  When writing the page header, the \a samples argument to the
- * write callback will be \c 0.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_write_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderWriteCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_client_data(OggFLAC__SeekableStreamEncoder *encoder, void *value);
-
-/** Get the current encoder state.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval OggFLAC__SeekableStreamEncoderState
- *    The current encoder state.
- */
-OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_get_state(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** Get the state of the underlying FLAC stream encoder.
- *  Useful when the seekable stream encoder state is
- *  \c OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__StreamEncoderState
- *    The FLAC stream encoder state.
- */
-OggFLAC_API FLAC__StreamEncoderState OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** Get the state of the underlying FLAC encoder's verify decoder.
- *  Useful when the seekable stream encoder state is
- *  \c OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR
- *  and the FLAC stream encoder state is
- *  \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__StreamDecoderState
- *    The FLAC verify decoder state.
- */
-OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_encoder_get_verify_decoder_state(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** Get the current encoder state as a C string.
- *  This version automatically resolves
- *  \c OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR
- *  by getting the FLAC stream encoder's resolved state.
- *
- * \param  encoder  A encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval const char *
- *    The encoder state as a C string.  Do not modify the contents.
- */
-OggFLAC_API const char *OggFLAC__seekable_stream_encoder_get_resolved_state_string(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** Get relevant values about the nature of a verify decoder error.
- *  Inherited from FLAC__stream_encoder_get_verify_decoder_error_stats().
- *  Useful when the seekable stream encoder state is
- *  \c OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR
- *  and the FLAC stream encoder state is
- *  \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR.
- *
- * \param  encoder  An encoder instance to query.
- * \param  absolute_sample  The absolute sample number of the mismatch.
- * \param  frame_number  The number of the frame in which the mismatch occurred.
- * \param  channel       The channel in which the mismatch occurred.
- * \param  sample        The number of the sample (relative to the frame) in
- *                       which the mismatch occurred.
- * \param  expected      The expected value for the sample in question.
- * \param  got           The actual value returned by the decoder.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code absolute_sample != NULL \endcode
- *    \code frame_number != NULL \endcode
- *    \code channel != NULL \endcode
- *    \code sample != NULL \endcode
- *    \code expected != NULL \endcode
- */
-OggFLAC_API void OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_verify()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__seekable_stream_encoder_set_verify().
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_verify(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_streamable_subset()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__seekable_stream_encoder_set_streamable_subset().
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_streamable_subset(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_do_mid_side_stereo()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo().
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_loose_mid_side_stereo()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo().
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_channels()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_channels().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_channels(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_bits_per_sample()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_bits_per_sample().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_bits_per_sample(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_sample_rate()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_sample_rate().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_sample_rate(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_blocksize()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_blocksize().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_blocksize(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_max_lpc_order()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_max_lpc_order().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_max_lpc_order(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_qlp_coeff_precision()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_do_qlp_coeff_prec_search()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search().
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_do_escape_coding()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__seekable_stream_encoder_set_do_escape_coding().
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_escape_coding(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_do_exhaustive_model_search()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    See OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search().
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_min_residual_partition_order()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_min_residual_partition_order().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_man_residual_partition_order()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_max_residual_partition_order().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_rice_parameter_search_dist()
- *
- * \param  encoder  An encoder instance to query.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval unsigned
- *    See OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist().
- */
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_get_total_samples_estimate()
- *
- * \param  encoder  An encoder instance to set.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__uint64
- *    See OggFLAC__seekable_stream_encoder_get_total_samples_estimate().
- */
-OggFLAC_API FLAC__uint64 OggFLAC__seekable_stream_encoder_get_total_samples_estimate(const OggFLAC__SeekableStreamEncoder *encoder);
-
-/** Initialize the encoder instance.
- *  Should be called after OggFLAC__seekable_stream_encoder_new() and
- *  OggFLAC__seekable_stream_encoder_set_*() but before OggFLAC__seekable_stream_encoder_process()
- *  or OggFLAC__seekable_stream_encoder_process_interleaved().  Will set and return
- *  the encoder state, which will be OggFLAC__SEEKABLE_STREAM_ENCODER_OK if
- *  initialization succeeded.
- *
- *  The call to OggFLAC__seekable_stream_encoder_init() currently will also immediately
- *  call the write callback several times, once with the \c fLaC signature,
- *  and once for each encoded metadata block.
- *
- * \param  encoder  An uninitialized encoder instance.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval OggFLAC__SeekableStreamEncoderState
- *    \c OggFLAC__SEEKABLE_STREAM_ENCODER_OK if initialization was successful; see
- *    OggFLAC__SeekableStreamEncoderState for the meanings of other return values.
- */
-OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_init(OggFLAC__SeekableStreamEncoder *encoder);
-
-/** Finish the encoding process.
- *  Flushes the encoding buffer, releases resources, resets the encoder
- *  settings to their defaults, and returns the encoder state to
- *  OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED.  Note that this can generate
- *  one or more write callbacks before returning.
- *
- *  In the event of a prematurely-terminated encode, it is not strictly
- *  necessary to call this immediately before OggFLAC__seekable_stream_encoder_delete()
- *  but it is good practice to match every OggFLAC__seekable_stream_encoder_init()
- *  with an OggFLAC__seekable_stream_encoder_finish().
- *
- * \param  encoder  An uninitialized encoder instance.
- * \assert
- *    \code encoder != NULL \endcode
- */
-OggFLAC_API void OggFLAC__seekable_stream_encoder_finish(OggFLAC__SeekableStreamEncoder *encoder);
-
-/** Submit data for encoding.
- * This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_process().
- *
- * \param  encoder  An initialized encoder instance in the OK state.
- * \param  buffer   An array of pointers to each channel's signal.
- * \param  samples  The number of samples in one channel.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code OggFLAC__seekable_stream_encoder_get_state(encoder) == OggFLAC__SEEKABLE_STREAM_ENCODER_OK \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false; in this case, check the
- *    encoder state with OggFLAC__seekable_stream_encoder_get_state() to see what
- *    went wrong.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_process(OggFLAC__SeekableStreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples);
-
-/** Submit data for encoding.
- * This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_process_interleaved().
- *
- * \param  encoder  An initialized encoder instance in the OK state.
- * \param  buffer   An array of channel-interleaved data (see above).
- * \param  samples  The number of samples in one channel, the same as for
- *                  OggFLAC__seekable_stream_encoder_process().  For example, if
- *                  encoding two channels, \c 1000 \a samples corresponds
- *                  to a \a buffer of 2000 values.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code OggFLAC__seekable_stream_encoder_get_state(encoder) == OggFLAC__SEEKABLE_STREAM_ENCODER_OK \endcode
- * \retval FLAC__bool
- *    \c true if successful, else \c false; in this case, check the
- *    encoder state with OggFLAC__seekable_stream_encoder_get_state() to see what
- *    went wrong.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_process_interleaved(OggFLAC__SeekableStreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples);
-
-/* \} */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
index 7634688..b855feb 100644 (file)
@@ -32,8 +32,8 @@
 #ifndef OggFLAC__STREAM_DECODER_H
 #define OggFLAC__STREAM_DECODER_H
 
+#include <stdio.h> /* for FILE */
 #include "export.h"
-
 #include "FLAC/stream_decoder.h"
 
 #ifdef __cplusplus
@@ -95,28 +95,31 @@ typedef enum {
        OggFLAC__STREAM_DECODER_OGG_ERROR,
        /**< An error occurred in the underlying Ogg layer.  */
 
-       OggFLAC__STREAM_DECODER_READ_ERROR,
-       /**< The read callback returned an error. */
-
        OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR,
        /**< An error occurred in the underlying FLAC stream decoder;
         * check OggFLAC__stream_decoder_get_FLAC_stream_decoder_state().
         */
 
-       OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
-
-       OggFLAC__STREAM_DECODER_ALREADY_INITIALIZED,
-       /**< OggFLAC__stream_decoder_init() was called when the decoder was
-        * already initialized, usually because
-        * OggFLAC__stream_decoder_finish() was not called.
+       OggFLAC__STREAM_DECODER_SEEK_ERROR,
+       /**< An error occurred while seeking or the seek or tell
+        * callback returned an error.  The decoder must be flushed with
+        * OggFLAC__stream_decoder_flush() or reset with
+        * OggFLAC__stream_decoder_reset() before decoding can continue.
         */
 
-       OggFLAC__STREAM_DECODER_INVALID_CALLBACK,
-       /**< The decoder was initialized before setting all the required callbacks. */
+       OggFLAC__STREAM_DECODER_READ_ERROR,
+       /**< The read callback returned an error. */
+
+       OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
+       /**< An error occurred allocating memory.  The decoder is in an invalid
+        * state and can no longer be used.
+        */
 
        OggFLAC__STREAM_DECODER_UNINITIALIZED
-       /**< The decoder is in the uninitialized state. */
+       /**< The decoder is in the uninitialized state; one of the
+        * OggFLAC__stream_decoder_init_*() functions must be called before samples
+        * can be processed.
+        */
 
 } OggFLAC__StreamDecoderState;
 
@@ -141,71 +144,11 @@ struct OggFLAC__StreamDecoderPrivate;
  *  for a detailed description.
  */
 typedef struct {
+       FLAC__StreamDecoder super_; /* parentclass@@@@@@ */
        struct OggFLAC__StreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */
        struct OggFLAC__StreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */
 } OggFLAC__StreamDecoder;
 
-/** Signature for the read callback.
- *  See OggFLAC__stream_decoder_set_read_callback()
- *  and FLAC__StreamDecoderReadCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  buffer   A pointer to a location for the callee to store
- *                  data to be decoded.
- * \param  bytes    A pointer to the size of the buffer.  On entry
- *                  to the callback, it contains the maximum number
- *                  of bytes that may be stored in \a buffer.  The
- *                  callee must set it to the actual number of bytes
- *                  stored before returning.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__stream_decoder_set_client_data().
- * \retval FLAC__StreamDecoderReadStatus
- *    The callee's return status.
- */
-typedef FLAC__StreamDecoderReadStatus (*OggFLAC__StreamDecoderReadCallback)(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-
-/** Signature for the write callback.
- *  See OggFLAC__stream_decoder_set_write_callback()
- *  and FLAC__StreamDecoderWriteCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  frame    The description of the decoded frame.  See
- *                  FLAC__Frame.
- * \param  buffer   An array of pointers to decoded channels of data.
- *                  Each pointer will point to an array of signed
- *                  samples of length \a frame->header.blocksize.
- *                  Currently, the channel order has no meaning
- *                  except for stereo streams; in this case channel
- *                  0 is left and 1 is right.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__stream_decoder_set_client_data().
- * \retval FLAC__StreamDecoderWriteStatus
- *    The callee's return status.
- */
-typedef FLAC__StreamDecoderWriteStatus (*OggFLAC__StreamDecoderWriteCallback)(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-
-/** Signature for the metadata callback.
- *  See OggFLAC__stream_decoder_set_metadata_callback()
- *  and FLAC__StreamDecoderMetadataCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  metadata The decoded metadata block.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__stream_decoder_set_client_data().
- */
-typedef void (*OggFLAC__StreamDecoderMetadataCallback)(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-
-/** Signature for the error callback.
- *  See OggFLAC__stream_decoder_set_error_callback()
- *  and FLAC__StreamDecoderErrorCallback for more info.
- *
- * \param  decoder  The decoder instance calling the callback.
- * \param  status   The error encountered by the decoder.
- * \param  client_data  The callee's client data set through
- *                      OggFLAC__stream_decoder_set_client_data().
- */
-typedef void (*OggFLAC__StreamDecoderErrorCallback)(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-
 
 /***********************************************************************
  *
@@ -237,88 +180,6 @@ OggFLAC_API void OggFLAC__stream_decoder_delete(OggFLAC__StreamDecoder *decoder)
  *
  ***********************************************************************/
 
-/** Set the read callback.
- * This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_set_read_callback()
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_read_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderReadCallback value);
-
-/** Set the write callback.
- * This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_set_write_callback()
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_write_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderWriteCallback value);
-
-/** Set the metadata callback.
- * This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_set_metadata_callback()
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderMetadataCallback value);
-
-/** Set the error callback.
- * This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_set_error_callback()
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_error_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderErrorCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  decoder  A decoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code decoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the decoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_client_data(OggFLAC__StreamDecoder *decoder, void *value);
-
 /** Set the serial number for the Ogg stream.
  * The default behavior is to use the serial number of the first Ogg
  * page.  Setting a serial number here will explicitly specify which
@@ -334,6 +195,19 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_client_data(OggFLAC__StreamDe
  */
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_serial_number(OggFLAC__StreamDecoder *decoder, long serial_number);
 
+/** Set the "MD5 signature checking" flag.
+ * This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_set_md5_checking()
+ *
+ * \default \c false
+ * \param  decoder  A decoder instance to set.
+ * \param  value    Flag value (see above).
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if the decoder is already initialized, else \c true.
+ */
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_md5_checking(OggFLAC__StreamDecoder *decoder, FLAC__bool value);
+
 /** Direct the decoder to pass on all metadata blocks of type \a type.
  * This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_set_metadata_respond()
  *
@@ -457,6 +331,26 @@ OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_decoder_get_FLAC_stream_dec
  */
 OggFLAC_API const char *OggFLAC__stream_decoder_get_resolved_state_string(const OggFLAC__StreamDecoder *decoder);
 
+/** This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_get_md5_checking()
+ *
+ * \param  decoder  A decoder instance to query.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ *    See above.
+ */
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_get_md5_checking(const OggFLAC__StreamDecoder *decoder);
+
+/** This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_get_total_samples()
+ *
+ * \param  decoder  A decoder instance to query.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval unsigned
+ *    See above.
+ */
+OggFLAC_API FLAC__uint64 OggFLAC__stream_decoder_get_total_samples(const OggFLAC__StreamDecoder *decoder);
+
 /** This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_get_channels()
  *
  * \param  decoder  A decoder instance to query.
@@ -508,21 +402,168 @@ OggFLAC_API unsigned OggFLAC__stream_decoder_get_sample_rate(const OggFLAC__Stre
 OggFLAC_API unsigned OggFLAC__stream_decoder_get_blocksize(const OggFLAC__StreamDecoder *decoder);
 
 /** Initialize the decoder instance.
- *  Should be called after OggFLAC__stream_decoder_new() and
+ *
+ *  This flavor of initialization sets up the decoder to decode from a stream.
+ *  I/O is performed via callbacks to the client.  For decoding from a plain file
+ *  via filename or open FILE*, OggFLAC__stream_decoder_init_file() and
+ *  OggFLAC__stream_decoder_init_FILE() provide a simpler interface.
+ *
+ *  This function should be called after OggFLAC__stream_decoder_new() and
  *  OggFLAC__stream_decoder_set_*() but before any of the
  *  OggFLAC__stream_decoder_process_*() functions.  Will set and return the
  *  decoder state, which will be OggFLAC__STREAM_DECODER_OK
  *  if initialization succeeded.
  *
- * \param  decoder  An uninitialized decoder instance.
+ * \param  decoder            An uninitialized decoder instance.
+ * \param  read_callback      See FLAC__StreamDecoderReadCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  seek_callback      See FLAC__StreamDecoderSeekCallback.  This
+ *                            pointer may be \c NULL if seeking is not
+ *                            supported.  If \a seek_callback is not \c NULL then a
+ *                            \a tell_callback, \a length_callback, and \a eof_callback must also be supplied.
+ *                            Alternatively, a dummy seek callback that just
+ *                            returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  tell_callback      See FLAC__StreamDecoderTellCallback.  This
+ *                            pointer may be \c NULL if not supported by the client.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a tell_callback must also be supplied.
+ *                            Alternatively, a dummy tell callback that just
+ *                            returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  length_callback    See FLAC__StreamDecoderLengthCallback.  This
+ *                            pointer may be \c NULL if not supported by the client.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a length_callback must also be supplied.
+ *                            Alternatively, a dummy length callback that just
+ *                            returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  eof_callback       See FLAC__StreamDecoderEofCallback.  This
+ *                            pointer may be \c NULL if not supported by the client.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a eof_callback must also be supplied.
+ *                            Alternatively, a dummy length callback that just
+ *                            returns \c false
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  write_callback     See FLAC__StreamDecoderWriteCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  metadata_callback  See FLAC__StreamDecoderMetadataCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  error_callback     See FLAC__StreamDecoderErrorCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
  * \assert
  *    \code decoder != NULL \endcode
- * \retval OggFLAC__StreamDecoderState
- *    \c OggFLAC__STREAM_DECODER_OK if initialization was
- *    successful; see OggFLAC__StreamDecoderState for the meanings of other
- *    return values.
- */
-OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__stream_decoder_init(OggFLAC__StreamDecoder *decoder);
+ * \retval FLAC__StreamDecoderInitStatus
+ *    \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamDecoderInitStatus for the meanings of other return values.
+ */
+OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_stream(
+       OggFLAC__StreamDecoder *decoder,
+       FLAC__StreamDecoderReadCallback read_callback,
+       FLAC__StreamDecoderSeekCallback seek_callback,
+       FLAC__StreamDecoderTellCallback tell_callback,
+       FLAC__StreamDecoderLengthCallback length_callback,
+       FLAC__StreamDecoderEofCallback eof_callback,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+);
+
+/** Initialize the decoder instance.
+ *
+ *  This flavor of initialization sets up the decoder to decode from a plain
+ *  file.  For non-stdio streams, you must use
+ *  OggFLAC__stream_decoder_init_stream() and provide callbacks for the I/O.
+ *
+ *  This function should be called after OggFLAC__stream_decoder_new() and
+ *  OggFLAC__stream_decoder_set_*() but before any of the
+ *  OggFLAC__stream_decoder_process_*() functions.  Will set and return the
+ *  decoder state, which will be OggFLAC__STREAM_DECODER_OK
+ *  if initialization succeeded.
+ *
+ * \param  decoder            An uninitialized decoder instance.
+ * \param  file               An open Ogg FLAC file.  The file should have been
+ *                            opened with mode \c "rb" and rewound.  The file
+ *                            becomes owned by the decoder and should not be
+ *                            manipulated by the client while decoding.
+ *                            Unless \a file is \c stdin, it will be closed
+ *                            when OggFLAC__stream_decoder_finish() is called.
+ *                            Note however that seeking will not work when
+ *                            decoding from \c stdout since it is not seekable.
+ * \param  write_callback     See FLAC__StreamDecoderWriteCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  metadata_callback  See FLAC__StreamDecoderMetadataCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  error_callback     See FLAC__StreamDecoderErrorCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code decoder != NULL \endcode
+ *    \code file != NULL \endcode
+ * \retval FLAC__StreamDecoderInitStatus
+ *    \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamDecoderInitStatus for the meanings of other return values.
+ */
+OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_FILE(
+       OggFLAC__StreamDecoder *decoder,
+       FILE *file,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+);
+
+/** Initialize the decoder instance.
+ *
+ *  This flavor of initialization sets up the decoder to decode from a plain
+ *  file.  If POSIX fopen() semantics are not sufficient, (for example, with
+ *  Unicode filenames on Windows), you must use
+ *  OggFLAC__stream_decoder_init_FILE(), or OggFLAC__stream_decoder_init_stream()
+ *  and provide callbacks for the I/O.
+ *
+ *  This function should be called after OggFLAC__stream_decoder_new() and
+ *  OggFLAC__stream_decoder_set_*() but before any of the
+ *  OggFLAC__stream_decoder_process_*() functions.  Will set and return the
+ *  decoder state, which will be OggFLAC__STREAM_DECODER_OK
+ *  if initialization succeeded.
+ *
+ * \param  decoder            An uninitialized decoder instance.
+ * \param  filename           The name of the file to decode from.  The file will
+ *                            be opened with fopen().  Use \c NULL to decode from
+ *                            \c stdin.  Note that \c stdin is not seekable.
+ * \param  write_callback     See FLAC__StreamDecoderWriteCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  metadata_callback  See FLAC__StreamDecoderMetadataCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  error_callback     See FLAC__StreamDecoderErrorCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval FLAC__StreamDecoderInitStatus
+ *    \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamDecoderInitStatus for the meanings of other return values.
+ */
+OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_file(
+       OggFLAC__StreamDecoder *decoder,
+       const char *filename,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+);
 
 /** Finish the decoding process.
  *  Flushes the decoding buffer, releases resources, resets the decoder
@@ -538,7 +579,7 @@ OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__stream_decoder_init(OggFLAC__St
  * \assert
  *    \code decoder != NULL \endcode
  */
-OggFLAC_API void OggFLAC__stream_decoder_finish(OggFLAC__StreamDecoder *decoder);
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_finish(OggFLAC__StreamDecoder *decoder);
 
 /** This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_flush()
  *
@@ -558,7 +599,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_flush(OggFLAC__StreamDecoder *dec
  *    \code decoder != NULL \endcode
  * \retval FLAC__bool
  *    \c true if successful, else \c false if a memory allocation
- *    error occurs.
+ *    or seek error occurs.
  */
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_reset(OggFLAC__StreamDecoder *decoder);
 
@@ -610,6 +651,35 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_metadata(Ogg
  */
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_stream(OggFLAC__StreamDecoder *decoder);
 
+/** Skip one audio frame.
+ *  This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_skip_single_frame()
+ *
+ * \param  decoder  An initialized decoder instance not in a metadata
+ *                  state.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ *    \c false if any fatal read, write, or memory allocation error
+ *    occurred (meaning decoding must stop), or if the underlying FLAC
+ *    stream decoder is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or
+ *    FLAC__STREAM_DECODER_READ_METADATA state, else \c true; for more
+ *    information about the decoder, check the decoder state with
+ *    OggFLAC__stream_decoder_get_FLAC_stream_decoder_state().
+ */
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_skip_single_frame(OggFLAC__StreamDecoder *decoder);
+
+/** Flush the input and seek to an absolute sample.
+ *  This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_seek_absolute().
+ *
+ * \param  decoder  A decoder instance.
+ * \param  sample   The target sample number to seek to.
+ * \assert
+ *    \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ *    \c true if successful, else \c false.
+ */
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_seek_absolute(OggFLAC__StreamDecoder *decoder, FLAC__uint64 sample);
+
 /* \} */
 
 #ifdef __cplusplus
index e2ebb4b..2774d61 100644 (file)
@@ -88,7 +88,13 @@ extern "C" {
 typedef enum {
 
        OggFLAC__STREAM_ENCODER_OK = 0,
-       /**< The encoder is in the normal OK state. */
+       /**< The encoder is in the normal OK state and samples can be processed. */
+
+       OggFLAC__STREAM_ENCODER_UNINITIALIZED,
+       /**< The encoder is in the uninitialized state; one of the
+        * OggFLAC__stream_encoder_init_*() functions must be called before samples
+        * can be processed.
+        */
 
        OggFLAC__STREAM_ENCODER_OGG_ERROR,
        /**< An error occurred in the underlying Ogg layer.  */
@@ -98,20 +104,16 @@ typedef enum {
         * check OggFLAC__stream_encoder_get_FLAC_stream_encoder_state().
         */
 
-       OggFLAC__STREAM_ENCODER_INVALID_CALLBACK,
-       /**< The encoder was initialized before setting all the required callbacks. */
-
-       OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR,
-       /**< Memory allocation failed. */
+       OggFLAC__STREAM_ENCODER_CLIENT_ERROR,
+       /**< One of the callbacks returned a fatal error. */
 
-       OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED,
-       /**< OggFLAC__stream_encoder_init() was called when the encoder was
-        * already initialized, usually because
-        * OggFLAC__stream_encoder_finish() was not called.
+       OggFLAC__STREAM_ENCODER_IO_ERROR,
+       /**< An I/O error occurred while opening/reading/writing a file.
+        * Check \c errno.
         */
 
-       OggFLAC__STREAM_ENCODER_UNINITIALIZED
-       /**< The encoder is in the uninitialized state. */
+       OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR
+       /**< Memory allocation failed. */
 
 } OggFLAC__StreamEncoderState;
 
@@ -123,6 +125,32 @@ typedef enum {
 extern OggFLAC_API const char * const OggFLAC__StreamEncoderStateString[];
 
 
+/** Return values for the OggFLAC__StreamEncoder read callback.
+ */
+typedef enum {
+
+       OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE,
+       /**< The read was OK and decoding can continue. */
+
+       OggFLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM,
+       /**< The read was attempted at the end of the stream. */
+
+       OggFLAC__STREAM_ENCODER_READ_STATUS_ABORT,
+       /**< An unrecoverable error occurred. */
+
+       OggFLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED
+       /**< Client does not support reading back from the output. */
+
+} OggFLAC__StreamEncoderReadStatus;
+
+/** Maps a OggFLAC__StreamEncoderReadStatus to a C string.
+ *
+ *  Using a OggFLAC__StreamEncoderReadStatus as the index to this array
+ *  will give the string equivalent.  The contents should not be modified.
+ */
+extern OggFLAC_API const char * const OggFLAC__StreamEncoderReadStatusString[];
+
+
 /***********************************************************************
  *
  * class OggFLAC__StreamEncoder
@@ -136,38 +164,42 @@ struct OggFLAC__StreamEncoderPrivate;
  *  for a detailed description.
  */
 typedef struct {
+       FLAC__StreamEncoder super_; /* parentclass@@@@@@ */
        struct OggFLAC__StreamEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */
        struct OggFLAC__StreamEncoderPrivate *private_; /* avoid the C++ keyword 'private' */
 } OggFLAC__StreamEncoder;
 
-/** Signature for the write callback.
- *  See OggFLAC__stream_encoder_set_write_callback()
- *  and FLAC__StreamEncoderWriteCallback for more info.
+/** Signature for the read callback.
+ *
+ *  A function pointer matching this signature must be passed to
+ *  OggFLAC__stream_encoder_init_stream() if seeking is supported.
+ *  The supplied function will be called when the encoder needs to read back
+ *  encoded data.  This happens during the metadata callback, when the encoder
+ *  has to read, modify, and rewrite the metadata (e.g. seekpoints) gathered
+ *  while encoding.  The address of the buffer to be filled is supplied, along
+ *  with the number of bytes the buffer can hold.  The callback may choose to
+ *  supply less data and modify the byte count but must be careful not to
+ *  overflow the buffer.  The callback then returns a status code chosen from
+ *  OggFLAC__StreamEncoderReadStatus.
+ *
+ * \note In general, FLAC__StreamEncoder functions which change the
+ * state should not be called on the \a encoder while in the callback.
  *
  * \param  encoder  The encoder instance calling the callback.
- * \param  buffer   An array of encoded data of length \a bytes.
- * \param  bytes    The byte length of \a buffer.
- * \param  samples  The number of samples encoded by \a buffer.
- *                  \c 0 has a special meaning; see
- *                  OggFLAC__stream_encoder_set_write_callback().
- * \param  current_frame  The number of current frame being encoded.
+ * \param  buffer   A pointer to a location for the callee to store
+ *                  data to be encoded.
+ * \param  bytes    A pointer to the size of the buffer.  On entry
+ *                  to the callback, it contains the maximum number
+ *                  of bytes that may be stored in \a buffer.  The
+ *                  callee must set it to the actual number of bytes
+ *                  stored (0 in case of error or end-of-stream) before
+ *                  returning.
  * \param  client_data  The callee's client data set through
  *                      OggFLAC__stream_encoder_set_client_data().
- * \retval FLAC__StreamEncoderWriteStatus
+ * \retval OggFLAC__StreamEncoderReadStatus
  *    The callee's return status.
  */
-typedef FLAC__StreamEncoderWriteStatus (*OggFLAC__StreamEncoderWriteCallback)(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-
-/** Signature for the metadata callback.
- *  See OggFLAC__stream_encoder_set_metadata_callback()
- *  and FLAC__stream_encoder_set_metadata_callback() for more info.
- *
- * \param  encoder      The encoder instance calling the callback.
- * \param  metadata     The final populated STREAMINFO block.
- * \param  client_data  The callee's client data set through
- *                      FLAC__stream_encoder_set_client_data().
- */
-typedef void (*OggFLAC__StreamEncoderMetadataCallback)(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
+typedef OggFLAC__StreamEncoderReadStatus (*OggFLAC__StreamEncoderReadCallback)(const OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
 
 
 /***********************************************************************
@@ -460,63 +492,6 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLA
  */
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks);
 
-/** Set the write callback.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_write_callback().
- *
- * \note
- * Unlike the FLAC stream encoder write callback, the Ogg stream
- * encoder write callback will be called twice when writing audio
- * frames; once for the page header, and once for the page body.
- * When writing the page header, the \a samples argument to the
- * write callback will be \c 0.
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_write_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderWriteCallback value);
-
-/** Set the metadata callback.
- *  This is inherited from FLAC__StreamEncoder; see
- *  FLAC__stream_encoder_set_metadata_callback().
- *
- * \note
- * The callback is mandatory and must be set before initialization.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- *    \code value != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderMetadataCallback value);
-
-/** Set the client data to be passed back to callbacks.
- *  This value will be supplied to callbacks in their \a client_data
- *  argument.
- *
- * \default \c NULL
- * \param  encoder  An encoder instance to set.
- * \param  value    See above.
- * \assert
- *    \code encoder != NULL \endcode
- * \retval FLAC__bool
- *    \c false if the encoder is already initialized, else \c true.
- */
-OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_client_data(OggFLAC__StreamEncoder *encoder, void *value);
-
 /** Get the current encoder state.
  *
  * \param  encoder  An encoder instance to query.
@@ -780,6 +755,169 @@ OggFLAC_API FLAC__uint64 OggFLAC__stream_encoder_get_total_samples_estimate(cons
  */
 OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_init(OggFLAC__StreamEncoder *encoder);
 
+/** Initialize the encoder instance.
+ *
+ *  This flavor of initialization sets up the encoder to encode to a stream.
+ *  I/O is performed via callbacks to the client.  For encoding to a plain file
+ *  via filename or open \c FILE*, OggFLAC__stream_encoder_init_file() and
+ *  OggFLAC__stream_encoder_init_FILE() provide a simpler interface.
+ *
+ *  This function should be called after OggFLAC__stream_encoder_new() and
+ *  OggFLAC__stream_encoder_set_*() but before OggFLAC__stream_encoder_process()
+ *  or OggFLAC__stream_encoder_process_interleaved().
+ *  initialization succeeded.
+ *
+ *  The call to OggFLAC__stream_encoder_init_stream() currently will also immediately
+ *  call the write callback several times, once with the \c fLaC signature,
+ *  and once for each encoded metadata block.
+ *
+ * \note
+ * Unlike the FLAC stream encoder write callback, the Ogg stream
+ * encoder write callback will be called twice when writing each audio
+ * frame; once for the page header, and once for the page body.
+ * When writing the page header, the \a samples argument to the
+ * write callback will be \c 0.
+ *
+ * \param  encoder            An uninitialized encoder instance.
+ * \param  read_callback      See OggFLAC__StreamEncoderReadCallback.  This
+ *                            pointer must not be \c NULL if \a seek_callback
+ *                            is non-NULL since they are both needed to be
+ *                            able to write data back to the Ogg FLAC stream
+ *                            in the post-encode phase.
+ * \param  write_callback     See FLAC__StreamEncoderWriteCallback.  This
+ *                            pointer must not be \c NULL.
+ * \param  seek_callback      See FLAC__StreamEncoderSeekCallback.  This
+ *                            pointer may be \c NULL if seeking is not
+ *                            supported.  The encoder uses seeking to go back
+ *                            and write some some stream statistics to the
+ *                            STREAMINFO block; this is recommended but not
+ *                            necessary to create a valid FLAC stream.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a tell_callback must also be supplied.
+ *                            Alternatively, a dummy seek callback that just
+ *                            returns \c FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  tell_callback      See FLAC__StreamEncoderTellCallback.  This
+ *                            pointer may be \c NULL if seeking is not
+ *                            supported.  If \a seek_callback is \c NULL then
+ *                            this argument will be ignored.  If
+ *                            \a seek_callback is not \c NULL then a
+ *                            \a tell_callback must also be supplied.
+ *                            Alternatively, a dummy tell callback that just
+ *                            returns \c FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED
+ *                            may also be supplied, all though this is slightly
+ *                            less efficient for the decoder.
+ * \param  metadata_callback  See FLAC__StreamEncoderMetadataCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.  If the client provides a seek callback,
+ *                            this function is not necessary as the encoder
+ *                            will automatically seek back and update the
+ *                            STREAMINFO block.  It may also be \c NULL if the
+ *                            client does not support seeking, since it will
+ *                            have no way of going back to update the
+ *                            STREAMINFO.  However the client can still supply
+ *                            a callback if it would like to know the details
+ *                            from the STREAMINFO.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code encoder != NULL \endcode
+ * \retval FLAC__StreamEncoderInitStatus
+ *    \c FLAC__STREAM_ENCODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamEncoderInitStatus for the meanings of other return values.
+ */
+OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_stream(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderReadCallback read_callback, FLAC__StreamEncoderWriteCallback write_callback, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderTellCallback tell_callback, FLAC__StreamEncoderMetadataCallback metadata_callback, void *client_data);
+
+/** Initialize the encoder instance.
+ *
+ *  This flavor of initialization sets up the encoder to encode to a plain
+ *  file.  For non-stdio streams, you must use
+ *  OggFLAC__stream_encoder_init_stream() and provide callbacks for the I/O.
+ *
+ *  This function should be called after OggFLAC__stream_encoder_new() and
+ *  OggFLAC__stream_encoder_set_*() but before OggFLAC__stream_encoder_process()
+ *  or OggFLAC__stream_encoder_process_interleaved().
+ *  initialization succeeded.
+ *
+ *  The call to OggFLAC__stream_encoder_init_stream() currently will also immediately
+ *  call the write callback several times, once with the \c fLaC signature,
+ *  and once for each encoded metadata block.
+ *
+ * \note
+ * Unlike the FLAC stream encoder write callback, the Ogg stream
+ * encoder write callback will be called twice when writing each audio
+ * frame; once for the page header, and once for the page body.
+ * When writing the page header, the \a samples argument to the
+ * write callback will be \c 0.
+ *
+ * \param  encoder            An uninitialized encoder instance.
+ * \param  file               An open file.  The file should have been opened
+ *                            with mode \c "w+b" and rewound.  The file
+ *                            becomes owned by the encoder and should not be
+ *                            manipulated by the client while encoding.
+ *                            Unless \a file is \c stdout, it will be closed
+ *                            when OggFLAC__stream_encoder_finish() is called.
+ *                            Note however that a proper SEEKTABLE cannot be
+ *                            created when encoding to \c stdout since it is
+ *                            not seekable.
+ * \param  progress_callback  See FLAC__StreamEncoderProgressCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code encoder != NULL \endcode
+ *    \code file != NULL \endcode
+ * \retval FLAC__StreamEncoderInitStatus
+ *    \c FLAC__STREAM_ENCODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamEncoderInitStatus for the meanings of other return values.
+ */
+OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_FILE(OggFLAC__StreamEncoder *encoder, FILE *file, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data);
+
+/** Initialize the encoder instance.
+ *
+ *  This flavor of initialization sets up the encoder to encode to a plain
+ *  file.  If POSIX fopen() semantics are not sufficient (for example,
+ *  with Unicode filenames on Windows), you must use
+ *  OggFLAC__stream_encodeR_init_FILE(), or OggFLAC__stream_encoder_init_stream()
+ *  and provide callbacks for the I/O.
+ *
+ *  This function should be called after OggFLAC__stream_encoder_new() and
+ *  OggFLAC__stream_encoder_set_*() but before OggFLAC__stream_encoder_process()
+ *  or OggFLAC__stream_encoder_process_interleaved().
+ *  initialization succeeded.
+ *
+ *  The call to OggFLAC__stream_encoder_init_stream() currently will also immediately
+ *  call the write callback several times, once with the \c fLaC signature,
+ *  and once for each encoded metadata block.
+ *
+ * \note
+ * Unlike the FLAC stream encoder write callback, the Ogg stream
+ * encoder write callback will be called twice when writing each audio
+ * frame; once for the page header, and once for the page body.
+ * When writing the page header, the \a samples argument to the
+ * write callback will be \c 0.
+ *
+ * \param  encoder            An uninitialized encoder instance.
+ * \param  filename           The name of the file to encode to.  The file will
+ *                            be opened with fopen().  Use \c NULL to encode to
+ *                            \c stdout.  Note however that a proper SEEKTABLE
+ *                            cannot be created when encoding to \c stdout since
+ *                            it is not seekable.
+ * \param  progress_callback  See FLAC__StreamEncoderProgressCallback.  This
+ *                            pointer may be \c NULL if the callback is not
+ *                            desired.
+ * \param  client_data        This value will be supplied to callbacks in their
+ *                            \a client_data argument.
+ * \assert
+ *    \code encoder != NULL \endcode
+ * \retval FLAC__StreamEncoderInitStatus
+ *    \c FLAC__STREAM_ENCODER_INIT_STATUS_OK if initialization was successful;
+ *    see FLAC__StreamEncoderInitStatus for the meanings of other return values.
+ */
+OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_file(OggFLAC__StreamEncoder *encoder, const char *filename, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data);
+
 /** Finish the encoding process.
  *  Flushes the encoding buffer, releases resources, resets the encoder
  *  settings to their defaults, and returns the encoder state to
diff --git a/include/test_libs_common/Makefile.am b/include/test_libs_common/Makefile.am
new file mode 100644 (file)
index 0000000..8060b67
--- /dev/null
@@ -0,0 +1,13 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+if FLaC__HAS_OGG
+OGGFLAC_DIST = \
+       file_utils_oggflac.h
+endif
+
+EXTRA_DIST = \
+       file_utils_flac.h \
+       metadata_utils.h \
+       $(OGGFLAC_DIST)
index 0b5b5a4..2d97fe2 100644 (file)
@@ -35,6 +35,7 @@ SUBDIRS = \
        $(XMMS_DIRS) \
        plugin_winamp2 \
        test_grabbag \
+       test_libs_common \
        test_libFLAC \
        test_libFLAC++ \
        $(OGGFLAC_TEST_DIRS) \
index 0f1cbf3..f2c2bd2 100644 (file)
@@ -15,8 +15,8 @@
 #  restrictive of those mentioned above.  See the file COPYING.Xiph in this
 #  distribution.
 
-.PHONY: all flac libFLAC libFLAC++ libOggFLAC libOggFLAC++ metaflac plugin_common plugin_xmms share test_grabbag test_libFLAC test_libFLAC++ test_libOggFLAC test_libOggFLAC++ test_seeking test_streams
-all: flac libFLAC libFLAC++ libOggFLAC libOggFLAC++ metaflac plugin_common plugin_xmms share test_grabbag test_libFLAC test_libFLAC++ test_libOggFLAC test_libOggFLAC++ test_seeking test_streams
+.PHONY: all flac libFLAC libFLAC++ libOggFLAC libOggFLAC++ metaflac plugin_common plugin_xmms share test_grabbag test_libs_common test_libFLAC test_libFLAC++ test_libOggFLAC test_libOggFLAC++ test_seeking test_streams
+all: flac libFLAC libFLAC++ libOggFLAC libOggFLAC++ metaflac plugin_common plugin_xmms share test_grabbag test_libs_common test_libFLAC test_libFLAC++ test_libOggFLAC test_libOggFLAC++ test_seeking test_streams
 
 DEFAULT_CONFIG = release
 
@@ -30,7 +30,7 @@ debug   : all
 valgrind: all
 release : all
 
-flac libFLAC libFLAC++ libOggFLAC libOggFLAC++ metaflac plugin_common plugin_xmms share test_grabbag test_libFLAC test_libFLAC++ test_libOggFLAC test_libOggFLAC++ test_seeking test_streams:
+flac libFLAC libFLAC++ libOggFLAC libOggFLAC++ metaflac plugin_common plugin_xmms share test_grabbag test_libs_common test_libFLAC test_libFLAC++ test_libOggFLAC test_libOggFLAC++ test_seeking test_streams:
        (cd $@ ; $(MAKE) -f Makefile.lite $(CONFIG))
 
 clean:
@@ -44,6 +44,7 @@ clean:
        -(cd plugin_xmms ; $(MAKE) -f Makefile.lite clean)
        -(cd share ; $(MAKE) -f Makefile.lite clean)
        -(cd test_grabbag ; $(MAKE) -f Makefile.lite clean)
+       -(cd test_libs_common ; $(MAKE) -f Makefile.lite clean)
        -(cd test_libFLAC ; $(MAKE) -f Makefile.lite clean)
        -(cd test_libFLAC++ ; $(MAKE) -f Makefile.lite clean)
        -(cd test_libOggFLAC ; $(MAKE) -f Makefile.lite clean)
@@ -60,9 +61,9 @@ plugin_common: libFLAC
 plugin_xmms: libFLAC plugin_common
 share: libFLAC
 test_grabbag: share
-test_libFLAC++: libFLAC libFLAC++
-test_libFLAC: libFLAC
-test_libOggFLAC++: libFLAC libOggFLAC libOggFLAC++
-test_libOggFLAC: libFLAC libOggFLAC
+test_libFLAC++: libFLAC libFLAC++ test_libs_common
+test_libFLAC: libFLAC test_libs_common
+test_libOggFLAC++: libFLAC libOggFLAC libOggFLAC++ test_libs_common
+test_libOggFLAC: libFLAC libOggFLAC test_libs_common
 test_seeking: libFLAC libOggFLAC
 test_streams: libFLAC
index 59f7abf..426f008 100644 (file)
@@ -42,7 +42,7 @@
 #include "decode.h"
 
 #ifdef FLAC__HAS_OGG
-#include "OggFLAC/file_decoder.h"
+#include "OggFLAC/stream_decoder.h"
 #endif
 
 typedef struct {
@@ -88,13 +88,9 @@ typedef struct {
        unsigned sample_rate;
 
        union {
-               union {
-                       FLAC__FileDecoder *file;
-               } flac;
+               FLAC__StreamDecoder *flac;
 #ifdef FLAC__HAS_OGG
-               union {
-                       OggFLAC__FileDecoder *file;
-               } ogg;
+               OggFLAC__StreamDecoder *ogg;
 #endif
        } decoder;
 
@@ -122,14 +118,10 @@ static FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val);
 static FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val);
 static FLAC__bool write_sane_extended(FILE *f, unsigned val);
 static FLAC__bool fixup_iff_headers(DecoderSession *d);
-/*
- * We use 'void *' so that we can use the same callbacks for the
- * FLAC__StreamDecoder and FLAC__FileDecoder.  The 'decoder' argument is
- * actually never used in the callbacks.
- */
-static FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-static void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static void print_error_with_init_status(const DecoderSession *d, const char *message, FLAC__StreamDecoderInitStatus init_status);
 static void print_error_with_state(const DecoderSession *d, const char *message);
 static void print_stats(const DecoderSession *decoder_session);
 
@@ -287,9 +279,9 @@ FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__
        d->channels = 0;
        d->sample_rate = 0;
 
-       d->decoder.flac.file = 0;
+       d->decoder.flac = 0;
 #ifdef FLAC__HAS_OGG
-       d->decoder.ogg.file = 0;
+       d->decoder.ogg = 0;
 #endif
 
        d->fout = 0; /* initialized with an open file later if necessary */
@@ -326,40 +318,31 @@ void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred)
 
 FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, decode_options_t decode_options, const char *infilename)
 {
+       FLAC__StreamDecoderInitStatus init_status;
        FLAC__uint32 test = 1;
 
        is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true;
 
 #ifdef FLAC__HAS_OGG
        if(decoder_session->is_ogg) {
-               decoder_session->decoder.ogg.file = OggFLAC__file_decoder_new();
+               decoder_session->decoder.ogg = OggFLAC__stream_decoder_new();
 
-               if(0 == decoder_session->decoder.ogg.file) {
+               if(0 == decoder_session->decoder.ogg) {
                        flac__utils_printf(stderr, 1, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
                        return false;
                }
 
-               OggFLAC__file_decoder_set_md5_checking(decoder_session->decoder.ogg.file, true);
-               OggFLAC__file_decoder_set_filename(decoder_session->decoder.ogg.file, infilename);
+               OggFLAC__stream_decoder_set_md5_checking(decoder_session->decoder.ogg, true);
                if(!decode_options.use_first_serial_number)
-                       OggFLAC__file_decoder_set_serial_number(decoder_session->decoder.ogg.file, decode_options.serial_number);
+                       OggFLAC__stream_decoder_set_serial_number(decoder_session->decoder.ogg, decode_options.serial_number);
                if (0 != decoder_session->cue_specification)
-                       OggFLAC__file_decoder_set_metadata_respond(decoder_session->decoder.ogg.file, FLAC__METADATA_TYPE_CUESHEET);
+                       OggFLAC__stream_decoder_set_metadata_respond(decoder_session->decoder.ogg, FLAC__METADATA_TYPE_CUESHEET);
                if (decoder_session->replaygain.spec.apply)
-                       OggFLAC__file_decoder_set_metadata_respond(decoder_session->decoder.ogg.file, FLAC__METADATA_TYPE_VORBIS_COMMENT);
-
-               /*
-                * The three ugly casts here are to 'downcast' the 'void *' argument of
-                * the callback down to 'OggFLAC__FileDecoder *'.  In C++ this would be
-                * unnecessary but here the cast makes the C compiler happy.
-                */
-               OggFLAC__file_decoder_set_write_callback(decoder_session->decoder.ogg.file, (FLAC__StreamDecoderWriteStatus (*)(const OggFLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
-               OggFLAC__file_decoder_set_metadata_callback(decoder_session->decoder.ogg.file, (void (*)(const OggFLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
-               OggFLAC__file_decoder_set_error_callback(decoder_session->decoder.ogg.file, (void (*)(const OggFLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
-               OggFLAC__file_decoder_set_client_data(decoder_session->decoder.ogg.file, decoder_session);
-
-               if(OggFLAC__file_decoder_init(decoder_session->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK) {
-                       print_error_with_state(decoder_session, "ERROR initializing decoder");
+                       OggFLAC__stream_decoder_set_metadata_respond(decoder_session->decoder.ogg, FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+               init_status = OggFLAC__stream_decoder_init_file(decoder_session->decoder.ogg, strcmp(infilename, "-")? infilename : 0, write_callback, metadata_callback, error_callback, /*client_data=*/decoder_session);
+               if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+                       print_error_with_init_status(decoder_session, "ERROR initializing decoder", init_status);
                        return false;
                }
        }
@@ -368,30 +351,22 @@ FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, decode_o
        (void)decode_options;
 #endif
        {
-               decoder_session->decoder.flac.file = FLAC__file_decoder_new();
+               decoder_session->decoder.flac = FLAC__stream_decoder_new();
 
-               if(0 == decoder_session->decoder.flac.file) {
+               if(0 == decoder_session->decoder.flac) {
                        flac__utils_printf(stderr, 1, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
                        return false;
                }
 
-               FLAC__file_decoder_set_md5_checking(decoder_session->decoder.flac.file, true);
-               FLAC__file_decoder_set_filename(decoder_session->decoder.flac.file, infilename);
+               FLAC__stream_decoder_set_md5_checking(decoder_session->decoder.flac, true);
                if (0 != decoder_session->cue_specification)
-                       FLAC__file_decoder_set_metadata_respond(decoder_session->decoder.flac.file, FLAC__METADATA_TYPE_CUESHEET);
+                       FLAC__stream_decoder_set_metadata_respond(decoder_session->decoder.flac, FLAC__METADATA_TYPE_CUESHEET);
                if (decoder_session->replaygain.spec.apply)
-                       FLAC__file_decoder_set_metadata_respond(decoder_session->decoder.flac.file, FLAC__METADATA_TYPE_VORBIS_COMMENT);
-               /*
-                * The three ugly casts here are to 'downcast' the 'void *' argument of
-                * the callback down to 'FLAC__FileDecoder *'.
-                */
-               FLAC__file_decoder_set_write_callback(decoder_session->decoder.flac.file, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
-               FLAC__file_decoder_set_metadata_callback(decoder_session->decoder.flac.file, (void (*)(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
-               FLAC__file_decoder_set_error_callback(decoder_session->decoder.flac.file, (void (*)(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
-               FLAC__file_decoder_set_client_data(decoder_session->decoder.flac.file, decoder_session);
-
-               if(FLAC__file_decoder_init(decoder_session->decoder.flac.file) != FLAC__FILE_DECODER_OK) {
-                       print_error_with_state(decoder_session, "ERROR initializing decoder");
+                       FLAC__stream_decoder_set_metadata_respond(decoder_session->decoder.flac, FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+               init_status = FLAC__stream_decoder_init_file(decoder_session->decoder.flac, strcmp(infilename, "-")? infilename : 0, write_callback, metadata_callback, error_callback, /*client_data=*/decoder_session);
+               if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+                       print_error_with_init_status(decoder_session, "ERROR initializing decoder", init_status);
                        return false;
                }
        }
@@ -403,12 +378,12 @@ FLAC__bool DecoderSession_process(DecoderSession *d)
 {
 #ifdef FLAC__HAS_OGG
        if(d->is_ogg) {
-               if(!OggFLAC__file_decoder_process_until_end_of_metadata(d->decoder.ogg.file)) {
+               if(!OggFLAC__stream_decoder_process_until_end_of_metadata(d->decoder.ogg)) {
                        flac__utils_printf(stderr, 2, "\n");
                        print_error_with_state(d, "ERROR while decoding metadata");
                        return false;
                }
-               if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE) {
+               if(OggFLAC__stream_decoder_get_state(d->decoder.ogg) != OggFLAC__STREAM_DECODER_OK && OggFLAC__stream_decoder_get_state(d->decoder.ogg) != OggFLAC__STREAM_DECODER_END_OF_STREAM) {
                        flac__utils_printf(stderr, 2, "\n");
                        print_error_with_state(d, "ERROR during metadata decoding");
                        if(!d->continue_through_decode_errors)
@@ -418,12 +393,12 @@ FLAC__bool DecoderSession_process(DecoderSession *d)
        else
 #endif
        {
-               if(!FLAC__file_decoder_process_until_end_of_metadata(d->decoder.flac.file)) {
+               if(!FLAC__stream_decoder_process_until_end_of_metadata(d->decoder.flac)) {
                        flac__utils_printf(stderr, 2, "\n");
                        print_error_with_state(d, "ERROR while decoding metadata");
                        return false;
                }
-               if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE) {
+               if(FLAC__stream_decoder_get_state(d->decoder.flac) > FLAC__STREAM_DECODER_END_OF_STREAM) {
                        flac__utils_printf(stderr, 2, "\n");
                        print_error_with_state(d, "ERROR during metadata decoding");
                        if(!d->continue_through_decode_errors)
@@ -446,16 +421,16 @@ FLAC__bool DecoderSession_process(DecoderSession *d)
 
 #ifdef FLAC__HAS_OGG
                if(d->is_ogg) {
-                       if(!OggFLAC__file_decoder_seek_absolute(d->decoder.ogg.file, skip)) {
+                       if(!OggFLAC__stream_decoder_seek_absolute(d->decoder.ogg, skip)) {
                                print_error_with_state(d, "ERROR seeking while skipping bytes");
                                return false;
                        }
-                       if(!OggFLAC__file_decoder_process_until_end_of_file(d->decoder.ogg.file) && !d->aborting_due_to_until) {
+                       if(!OggFLAC__stream_decoder_process_until_end_of_stream(d->decoder.ogg) && !d->aborting_due_to_until) {
                                flac__utils_printf(stderr, 2, "\n");
                                print_error_with_state(d, "ERROR while decoding frames");
                                return false;
                        }
-                       if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) {
+                       if(OggFLAC__stream_decoder_get_state(d->decoder.ogg) != OggFLAC__STREAM_DECODER_OK && OggFLAC__stream_decoder_get_state(d->decoder.ogg) != OggFLAC__STREAM_DECODER_END_OF_STREAM && !d->aborting_due_to_until) {
                                flac__utils_printf(stderr, 2, "\n");
                                print_error_with_state(d, "ERROR during decoding");
                                return false;
@@ -464,16 +439,16 @@ FLAC__bool DecoderSession_process(DecoderSession *d)
                else
 #endif
                {
-                       if(!FLAC__file_decoder_seek_absolute(d->decoder.flac.file, skip)) {
+                       if(!FLAC__stream_decoder_seek_absolute(d->decoder.flac, skip)) {
                                print_error_with_state(d, "ERROR seeking while skipping bytes");
                                return false;
                        }
-                       if(!FLAC__file_decoder_process_until_end_of_file(d->decoder.flac.file) && !d->aborting_due_to_until) {
+                       if(!FLAC__stream_decoder_process_until_end_of_stream(d->decoder.flac) && !d->aborting_due_to_until) {
                                flac__utils_printf(stderr, 2, "\n");
                                print_error_with_state(d, "ERROR while decoding frames");
                                return false;
                        }
-                       if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) {
+                       if(FLAC__stream_decoder_get_state(d->decoder.flac) > FLAC__STREAM_DECODER_END_OF_STREAM && !d->aborting_due_to_until) {
                                flac__utils_printf(stderr, 2, "\n");
                                print_error_with_state(d, "ERROR during decoding");
                                return false;
@@ -483,12 +458,12 @@ FLAC__bool DecoderSession_process(DecoderSession *d)
        else {
 #ifdef FLAC__HAS_OGG
                if(d->is_ogg) {
-                       if(!OggFLAC__file_decoder_process_until_end_of_file(d->decoder.ogg.file) && !d->aborting_due_to_until) {
+                       if(!OggFLAC__stream_decoder_process_until_end_of_stream(d->decoder.ogg) && !d->aborting_due_to_until) {
                                flac__utils_printf(stderr, 2, "\n");
                                print_error_with_state(d, "ERROR while decoding data");
                                return false;
                        }
-                       if(OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_OK && OggFLAC__file_decoder_get_state(d->decoder.ogg.file) != OggFLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) {
+                       if(OggFLAC__stream_decoder_get_state(d->decoder.ogg) != OggFLAC__STREAM_DECODER_OK && OggFLAC__stream_decoder_get_state(d->decoder.ogg) != OggFLAC__STREAM_DECODER_END_OF_STREAM && !d->aborting_due_to_until) {
                                flac__utils_printf(stderr, 2, "\n");
                                print_error_with_state(d, "ERROR during decoding");
                                return false;
@@ -497,12 +472,12 @@ FLAC__bool DecoderSession_process(DecoderSession *d)
                else
 #endif
                {
-                       if(!FLAC__file_decoder_process_until_end_of_file(d->decoder.flac.file) && !d->aborting_due_to_until) {
+                       if(!FLAC__stream_decoder_process_until_end_of_stream(d->decoder.flac) && !d->aborting_due_to_until) {
                                flac__utils_printf(stderr, 2, "\n");
                                print_error_with_state(d, "ERROR while decoding data");
                                return false;
                        }
-                       if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE && !d->aborting_due_to_until) {
+                       if(FLAC__stream_decoder_get_state(d->decoder.flac) > FLAC__STREAM_DECODER_END_OF_STREAM && !d->aborting_due_to_until) {
                                flac__utils_printf(stderr, 2, "\n");
                                print_error_with_state(d, "ERROR during decoding");
                                return false;
@@ -510,7 +485,7 @@ FLAC__bool DecoderSession_process(DecoderSession *d)
                }
        }
 
-       if((d->is_wave_out || d->is_aiff_out) && ((d->total_samples * d->channels * ((d->bps+7)/8)) & 1)) {
+       if(!d->analysis_mode && !d->test_only && (d->is_wave_out || d->is_aiff_out) && ((d->total_samples * d->channels * ((d->bps+7)/8)) & 1)) {
                if(flac__utils_fwrite("\000", 1, 1, d->fout) != 1) {
                        print_error_with_state(d, d->is_wave_out?
                                "ERROR writing pad byte to WAVE data chunk" :
@@ -529,19 +504,19 @@ int DecoderSession_finish_ok(DecoderSession *d)
 
 #ifdef FLAC__HAS_OGG
        if(d->is_ogg) {
-               if(d->decoder.ogg.file) {
-                       md5_failure = !OggFLAC__file_decoder_finish(d->decoder.ogg.file) && !d->aborting_due_to_until;
+               if(d->decoder.ogg) {
+                       md5_failure = !OggFLAC__stream_decoder_finish(d->decoder.ogg) && !d->aborting_due_to_until;
                        print_stats(d);
-                       OggFLAC__file_decoder_delete(d->decoder.ogg.file);
+                       OggFLAC__stream_decoder_delete(d->decoder.ogg);
                }
        }
        else
 #endif
        {
-               if(d->decoder.flac.file) {
-                       md5_failure = !FLAC__file_decoder_finish(d->decoder.flac.file) && !d->aborting_due_to_until;
+               if(d->decoder.flac) {
+                       md5_failure = !FLAC__stream_decoder_finish(d->decoder.flac) && !d->aborting_due_to_until;
                        print_stats(d);
-                       FLAC__file_decoder_delete(d->decoder.flac.file);
+                       FLAC__stream_decoder_delete(d->decoder.flac);
                }
        }
        if(d->analysis_mode)
@@ -567,17 +542,17 @@ int DecoderSession_finish_error(DecoderSession *d)
 {
 #ifdef FLAC__HAS_OGG
        if(d->is_ogg) {
-               if(d->decoder.ogg.file) {
-                       OggFLAC__file_decoder_finish(d->decoder.ogg.file);
-                       OggFLAC__file_decoder_delete(d->decoder.ogg.file);
+               if(d->decoder.ogg) {
+                       OggFLAC__stream_decoder_finish(d->decoder.ogg);
+                       OggFLAC__stream_decoder_delete(d->decoder.ogg);
                }
        }
        else
 #endif
        {
-               if(d->decoder.flac.file) {
-                       FLAC__file_decoder_finish(d->decoder.flac.file);
-                       FLAC__file_decoder_delete(d->decoder.flac.file);
+               if(d->decoder.flac) {
+                       FLAC__stream_decoder_finish(d->decoder.flac);
+                       FLAC__stream_decoder_delete(d->decoder.flac);
                }
        }
        if(d->analysis_mode)
@@ -820,7 +795,7 @@ FLAC__bool fixup_iff_headers(DecoderSession *d)
        return true;
 }
 
-FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
        DecoderSession *decoder_session = (DecoderSession*)client_data;
        FILE *fout = decoder_session->fout;
@@ -1053,7 +1028,7 @@ FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__F
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
 
-void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        DecoderSession *decoder_session = (DecoderSession*)client_data;
        (void)decoder;
@@ -1144,7 +1119,7 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata
        }
 }
 
-void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
        DecoderSession *decoder_session = (DecoderSession*)client_data;
        (void)decoder;
@@ -1156,6 +1131,24 @@ void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status,
        }
 }
 
+void print_error_with_init_status(const DecoderSession *d, const char *message, FLAC__StreamDecoderInitStatus init_status)
+{
+       const int ilen = strlen(d->inbasefilename) + 1;
+
+       flac__utils_printf(stderr, 1, "\n%s: %s\n", d->inbasefilename, message);
+
+       flac__utils_printf(stderr, 1, "%*s init status = %s\n", ilen, "", FLAC__StreamDecoderInitStatusString[init_status]);
+
+       /* print out some more info for some errors: */
+       if (init_status == FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE) {
+               flac__utils_printf(stderr, 1,
+                       "\n"
+                       "An error occurred opening the input file; it is likely that it does not exist\n"
+                       "or is not readable.\n"
+               );
+       }
+}
+
 void print_error_with_state(const DecoderSession *d, const char *message)
 {
        const int ilen = strlen(d->inbasefilename) + 1;
@@ -1165,12 +1158,12 @@ void print_error_with_state(const DecoderSession *d, const char *message)
 
 #ifdef FLAC__HAS_OGG
        if(d->is_ogg) {
-               state_string = OggFLAC__file_decoder_get_resolved_state_string(d->decoder.ogg.file);
+               state_string = OggFLAC__stream_decoder_get_resolved_state_string(d->decoder.ogg);
        }
        else
 #endif
        {
-               state_string = FLAC__file_decoder_get_resolved_state_string(d->decoder.flac.file);
+               state_string = FLAC__stream_decoder_get_resolved_state_string(d->decoder.flac);
        }
 
        flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", state_string);
@@ -1190,18 +1183,6 @@ void print_error_with_state(const DecoderSession *d, const char *message)
                        d->inbasefilename, FLAC__VERSION_STRING
                );
        }
-       else if (
-               0 == strcmp(state_string, FLAC__FileDecoderStateString[FLAC__FILE_DECODER_ERROR_OPENING_FILE])
-#ifdef FLAC__HAS_OGG
-               || 0 == strcmp(state_string, OggFLAC__FileDecoderStateString[OggFLAC__FILE_DECODER_ERROR_OPENING_FILE])
-#endif
-       ) {
-               flac__utils_printf(stderr, 1,
-                       "\n"
-                       "An error occurred opening the input file; it is likely that it does not exist\n"
-                       "or is not readable.\n"
-               );
-       }
 }
 
 void print_stats(const DecoderSession *decoder_session)
index 8bafa5b..85c52f2 100644 (file)
@@ -44,7 +44,6 @@
 
 #ifdef FLAC__HAS_OGG
 #include "OggFLAC/stream_encoder.h"
-#include "OggFLAC/file_encoder.h"
 #endif
 
 #ifdef min
@@ -81,20 +80,10 @@ typedef struct {
        unsigned blocksize;
        unsigned stats_mask;
 
-       /*
-        * We use *.stream for encoding to stdout
-        * We use *.file for encoding to a regular file
-        */
        union {
-               union {
-                       FLAC__StreamEncoder *stream;
-                       FLAC__FileEncoder *file;
-               } flac;
+               FLAC__StreamEncoder *flac;
 #ifdef FLAC__HAS_OGG
-               union {
-                       OggFLAC__StreamEncoder *stream;
-                       OggFLAC__FileEncoder *file;
-               } ogg;
+               OggFLAC__StreamEncoder *ogg;
 #endif
        } encoder;
 
@@ -134,16 +123,10 @@ static FLAC__int32 *input_[FLAC__MAX_CHANNELS];
 extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
 extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
 extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__file_encoder_disable_constant_subframes(FLAC__FileEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__file_encoder_disable_fixed_subframes(FLAC__FileEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__file_encoder_disable_verbatim_subframes(FLAC__FileEncoder *encoder, FLAC__bool value);
 #ifdef FLAC__HAS_OGG
 extern FLAC__bool OggFLAC__stream_encoder_disable_constant_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value);
 extern FLAC__bool OggFLAC__stream_encoder_disable_fixed_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value);
 extern FLAC__bool OggFLAC__stream_encoder_disable_verbatim_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool OggFLAC__file_encoder_disable_constant_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-extern FLAC__bool OggFLAC__file_encoder_disable_fixed_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value);
-extern FLAC__bool OggFLAC__file_encoder_disable_verbatim_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value);
 #endif
 
 /*
@@ -158,24 +141,18 @@ static FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 *
 static FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e);
 static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input);
 static void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps);
-#ifdef FLAC__HAS_OGG
-static FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-static void ogg_stream_encoder_metadata_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void ogg_file_encoder_progress_callback(const OggFLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
-#endif
-static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
-static FLAC__SeekableStreamDecoderReadStatus flac_decoder_read_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-static FLAC__SeekableStreamDecoderSeekStatus flac_decoder_seek_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-static FLAC__SeekableStreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-static FLAC__SeekableStreamDecoderLengthStatus flac_decoder_length_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
-static FLAC__bool flac_decoder_eof_callback(const FLAC__SeekableStreamDecoder *decoder, void *client_data);
-static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-static void flac_decoder_metadata_callback(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void flac_decoder_error_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static void encoder_progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);
+static FLAC__StreamDecoderReadStatus flac_decoder_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamDecoderSeekStatus flac_decoder_seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+static FLAC__StreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+static FLAC__StreamDecoderLengthStatus flac_decoder_length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
+static FLAC__bool flac_decoder_eof_callback(const FLAC__StreamDecoder *decoder, void *client_data);
+static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+static void flac_decoder_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static void flac_decoder_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
 static FLAC__bool parse_cuesheet(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset);
 static void print_stats(const EncoderSession *encoder_session);
+static void print_error_with_init_status(const EncoderSession *e, const char *message, FLAC__StreamEncoderInitStatus init_status);
 static void print_error_with_state(const EncoderSession *e, const char *message);
 static void print_verify_error(EncoderSession *e);
 static FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn);
@@ -1150,7 +1127,7 @@ int flac__encode_raw(FILE *infile, off_t infilesize, const char *infilename, con
 int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, flac_encode_options_t options)
 {
        EncoderSession encoder_session;
-       FLAC__SeekableStreamDecoder *decoder = 0;
+       FLAC__StreamDecoder *decoder = 0;
        FLACDecoderData decoder_data;
        size_t i;
        int retval;
@@ -1182,37 +1159,28 @@ int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, co
        /*
         * set up FLAC decoder for the input
         */
-       if (0 == (decoder = FLAC__seekable_stream_decoder_new())) {
+       if (0 == (decoder = FLAC__stream_decoder_new())) {
                flac__utils_printf(stderr, 1, "%s: ERROR: creating decoder for FLAC input\n", encoder_session.inbasefilename);
                return EncoderSession_finish_error(&encoder_session);
        }
        if (!(
-               FLAC__seekable_stream_decoder_set_md5_checking(decoder, false) &&
-               FLAC__seekable_stream_decoder_set_read_callback(decoder, flac_decoder_read_callback) &&
-               FLAC__seekable_stream_decoder_set_seek_callback(decoder, flac_decoder_seek_callback) &&
-               FLAC__seekable_stream_decoder_set_tell_callback(decoder, flac_decoder_tell_callback) &&
-               FLAC__seekable_stream_decoder_set_length_callback(decoder, flac_decoder_length_callback) &&
-               FLAC__seekable_stream_decoder_set_eof_callback(decoder, flac_decoder_eof_callback) &&
-               FLAC__seekable_stream_decoder_set_write_callback(decoder, flac_decoder_write_callback) &&
-               FLAC__seekable_stream_decoder_set_metadata_callback(decoder, flac_decoder_metadata_callback) &&
-               FLAC__seekable_stream_decoder_set_error_callback(decoder, flac_decoder_error_callback) &&
-               FLAC__seekable_stream_decoder_set_client_data(decoder, &decoder_data) &&
-               FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder)
+               FLAC__stream_decoder_set_md5_checking(decoder, false) &&
+               FLAC__stream_decoder_set_metadata_respond_all(decoder)
        )) {
                flac__utils_printf(stderr, 1, "%s: ERROR: setting up decoder for FLAC input\n", encoder_session.inbasefilename);
                goto fubar1; /*@@@ yuck */
        }
 
-       if (FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) {
-               flac__utils_printf(stderr, 1, "%s: ERROR: initializing decoder for FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__seekable_stream_decoder_get_resolved_state_string(decoder));
+       if (FLAC__stream_decoder_init_stream(decoder, flac_decoder_read_callback, flac_decoder_seek_callback, flac_decoder_tell_callback, flac_decoder_length_callback, flac_decoder_eof_callback, flac_decoder_write_callback, flac_decoder_metadata_callback, flac_decoder_error_callback, /*client_data=*/&decoder_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+               flac__utils_printf(stderr, 1, "%s: ERROR: initializing decoder for FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder));
                goto fubar1; /*@@@ yuck */
        }
 
-       if (!FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder) || decoder_data.fatal_error) {
+       if (!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || decoder_data.fatal_error) {
                if (decoder_data.fatal_error)
                        flac__utils_printf(stderr, 1, "%s: ERROR: out of memory or too many metadata blocks while reading metadata in FLAC input\n", encoder_session.inbasefilename);
                else
-                       flac__utils_printf(stderr, 1, "%s: ERROR: reading metadata in FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__seekable_stream_decoder_get_resolved_state_string(decoder));
+                       flac__utils_printf(stderr, 1, "%s: ERROR: reading metadata in FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder));
                goto fubar1; /*@@@ yuck */
        }
 
@@ -1272,8 +1240,8 @@ int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, co
                 */
                decoder_data.samples_left_to_process = encoder_session.total_samples_to_encode;
                if(encoder_session.skip > 0) {
-                       if(!FLAC__seekable_stream_decoder_seek_absolute(decoder, encoder_session.skip)) {
-                               flac__utils_printf(stderr, 1, "%s: ERROR while skipping samples, FLAC decoder state = %s\n", encoder_session.inbasefilename, FLAC__seekable_stream_decoder_get_resolved_state_string(decoder));
+                       if(!FLAC__stream_decoder_seek_absolute(decoder, encoder_session.skip)) {
+                               flac__utils_printf(stderr, 1, "%s: ERROR while skipping samples, FLAC decoder state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder));
                                goto fubar2; /*@@@ yuck */
                        }
                }
@@ -1282,14 +1250,14 @@ int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, co
                 * now do samples from the file
                 */
                while(!decoder_data.fatal_error && decoder_data.samples_left_to_process > 0) {
-                       if(!FLAC__seekable_stream_decoder_process_single(decoder)) {
-                               flac__utils_printf(stderr, 1, "%s: ERROR: while decoding FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__seekable_stream_decoder_get_resolved_state_string(decoder));
+                       if(!FLAC__stream_decoder_process_single(decoder)) {
+                               flac__utils_printf(stderr, 1, "%s: ERROR: while decoding FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder));
                                goto fubar2; /*@@@ yuck */
                        }
                }
        }
 
-       FLAC__seekable_stream_decoder_delete(decoder);
+       FLAC__stream_decoder_delete(decoder);
        retval = EncoderSession_finish_ok(&encoder_session, -1, -1);
        /* have to wail until encoder is completely finished before deleting because of the final step of writing the seekpoint offsets */
        for(i = 0; i < decoder_data.num_metadata_blocks; i++)
@@ -1300,7 +1268,7 @@ fubar2:
        for(i = 0; i < decoder_data.num_metadata_blocks; i++)
                free(decoder_data.metadata_blocks[i]);
 fubar1:
-       FLAC__seekable_stream_decoder_delete(decoder);
+       FLAC__stream_decoder_delete(decoder);
        return EncoderSession_finish_error(&encoder_session);
 }
 
@@ -1343,11 +1311,9 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_
        e->blocksize = 0;
        e->stats_mask = 0;
 
-       e->encoder.flac.stream = 0;
-       e->encoder.flac.file = 0;
+       e->encoder.flac = 0;
 #ifdef FLAC__HAS_OGG
-       e->encoder.ogg.stream = 0;
-       e->encoder.ogg.file = 0;
+       e->encoder.ogg = 0;
 #endif
 
        e->fin = infile;
@@ -1365,40 +1331,20 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_
 
 #ifdef FLAC__HAS_OGG
        if(e->use_ogg) {
-               if(e->is_stdout) {
-                       e->encoder.ogg.stream = OggFLAC__stream_encoder_new();
-                       if(0 == e->encoder.ogg.stream) {
-                               flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename);
-                               EncoderSession_destroy(e);
-                               return false;
-                       }
-               }
-               else {
-                       e->encoder.ogg.file = OggFLAC__file_encoder_new();
-                       if(0 == e->encoder.ogg.file) {
-                               flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename);
-                               EncoderSession_destroy(e);
-                               return false;
-                       }
-               }
-       }
-       else
-#endif
-       if(e->is_stdout) {
-               e->encoder.flac.stream = FLAC__stream_encoder_new();
-               if(0 == e->encoder.flac.stream) {
+               e->encoder.ogg = OggFLAC__stream_encoder_new();
+               if(0 == e->encoder.ogg) {
                        flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename);
                        EncoderSession_destroy(e);
                        return false;
                }
        }
-       else {
-               e->encoder.flac.file = FLAC__file_encoder_new();
-               if(0 == e->encoder.flac.file) {
-                       flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename);
-                       EncoderSession_destroy(e);
-                       return false;
-               }
+       else
+#endif
+       e->encoder.flac = FLAC__stream_encoder_new();
+       if(0 == e->encoder.flac) {
+               flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename);
+               EncoderSession_destroy(e);
+               return false;
        }
 
        return true;
@@ -1413,32 +1359,16 @@ void EncoderSession_destroy(EncoderSession *e)
 
 #ifdef FLAC__HAS_OGG
        if(e->use_ogg) {
-               if(e->is_stdout) {
-                       if(0 != e->encoder.ogg.stream) {
-                               OggFLAC__stream_encoder_delete(e->encoder.ogg.stream);
-                               e->encoder.ogg.stream = 0;
-                       }
-               }
-               else {
-                       if(0 != e->encoder.ogg.file) {
-                               OggFLAC__file_encoder_delete(e->encoder.ogg.file);
-                               e->encoder.ogg.file = 0;
-                       }
+               if(0 != e->encoder.ogg) {
+                       OggFLAC__stream_encoder_delete(e->encoder.ogg);
+                       e->encoder.ogg = 0;
                }
        }
        else
 #endif
-       if(e->is_stdout) {
-               if(0 != e->encoder.flac.stream) {
-                       FLAC__stream_encoder_delete(e->encoder.flac.stream);
-                       e->encoder.flac.stream = 0;
-               }
-       }
-       else {
-               if(0 != e->encoder.flac.file) {
-                       FLAC__file_encoder_delete(e->encoder.flac.file);
-                       e->encoder.flac.file = 0;
-               }
+       if(0 != e->encoder.flac) {
+               FLAC__stream_encoder_delete(e->encoder.flac);
+               e->encoder.flac = 0;
        }
 
        if(0 != e->seek_table_template) {
@@ -1454,32 +1384,16 @@ int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_a
 
 #ifdef FLAC__HAS_OGG
        if(e->use_ogg) {
-               if(e->is_stdout) {
-                       if(e->encoder.ogg.stream) {
-                               fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.stream);
-                               OggFLAC__stream_encoder_finish(e->encoder.ogg.stream);
-                       }
-               }
-               else {
-                       if(e->encoder.ogg.file) {
-                               fse_state = OggFLAC__file_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.file);
-                               OggFLAC__file_encoder_finish(e->encoder.ogg.file);
-                       }
+               if(e->encoder.ogg) {
+                       fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg);
+                       OggFLAC__stream_encoder_finish(e->encoder.ogg);
                }
        }
        else
 #endif
-       if(e->is_stdout) {
-               if(e->encoder.flac.stream) {
-                       fse_state = FLAC__stream_encoder_get_state(e->encoder.flac.stream);
-                       FLAC__stream_encoder_finish(e->encoder.flac.stream);
-               }
-       }
-       else {
-               if(e->encoder.flac.file) {
-                       fse_state = FLAC__file_encoder_get_stream_encoder_state(e->encoder.flac.file);
-                       FLAC__file_encoder_finish(e->encoder.flac.file);
-               }
+       if(e->encoder.flac) {
+               fse_state = FLAC__stream_encoder_get_state(e->encoder.flac);
+               FLAC__stream_encoder_finish(e->encoder.flac);
        }
 
        if(e->total_samples_to_encode > 0) {
@@ -1514,20 +1428,12 @@ int EncoderSession_finish_error(EncoderSession *e)
 
 #ifdef FLAC__HAS_OGG
        if(e->use_ogg) {
-               if(e->is_stdout) {
-                       fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.stream);
-               }
-               else {
-                       fse_state = OggFLAC__file_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg.file);
-               }
+               fse_state = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(e->encoder.ogg);
        }
        else
 #endif
        if(e->is_stdout) {
-               fse_state = FLAC__stream_encoder_get_state(e->encoder.flac.stream);
-       }
-       else {
-               fse_state = FLAC__file_encoder_get_stream_encoder_state(e->encoder.flac.file);
+               fse_state = FLAC__stream_encoder_get_state(e->encoder.flac);
        }
 
        if(fse_state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
@@ -1547,6 +1453,7 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
        FLAC__StreamMetadata padding, *cuesheet = 0;
        FLAC__StreamMetadata *static_metadata[4];
        FLAC__StreamMetadata **metadata = static_metadata;
+       FLAC__StreamEncoderInitStatus init_status;
        const FLAC__bool is_cdda = (channels == 1 || channels == 2) && (bps == 16) && (sample_rate == 44100);
 
        e->replay_gain = options.replay_gain;
@@ -1791,146 +1698,69 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
 
 #ifdef FLAC__HAS_OGG
        if(e->use_ogg) {
-               if(e->is_stdout) {
-                       OggFLAC__stream_encoder_set_serial_number(e->encoder.ogg.stream, options.serial_number);
-                       OggFLAC__stream_encoder_set_verify(e->encoder.ogg.stream, options.verify);
-                       OggFLAC__stream_encoder_set_streamable_subset(e->encoder.ogg.stream, !options.lax);
-                       OggFLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.ogg.stream, options.do_mid_side);
-                       OggFLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder.ogg.stream, options.loose_mid_side);
-                       OggFLAC__stream_encoder_set_channels(e->encoder.ogg.stream, channels);
-                       OggFLAC__stream_encoder_set_bits_per_sample(e->encoder.ogg.stream, bps);
-                       OggFLAC__stream_encoder_set_sample_rate(e->encoder.ogg.stream, sample_rate);
-                       OggFLAC__stream_encoder_set_blocksize(e->encoder.ogg.stream, options.blocksize);
-                       OggFLAC__stream_encoder_set_apodization(e->encoder.ogg.stream, options.apodizations);
-                       OggFLAC__stream_encoder_set_max_lpc_order(e->encoder.ogg.stream, options.max_lpc_order);
-                       OggFLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.ogg.stream, options.qlp_coeff_precision);
-                       OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.ogg.stream, options.do_qlp_coeff_prec_search);
-                       OggFLAC__stream_encoder_set_do_escape_coding(e->encoder.ogg.stream, options.do_escape_coding);
-                       OggFLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder.ogg.stream, options.do_exhaustive_model_search);
-                       OggFLAC__stream_encoder_set_min_residual_partition_order(e->encoder.ogg.stream, options.min_residual_partition_order);
-                       OggFLAC__stream_encoder_set_max_residual_partition_order(e->encoder.ogg.stream, options.max_residual_partition_order);
-                       OggFLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder.ogg.stream, options.rice_parameter_search_dist);
-                       OggFLAC__stream_encoder_set_total_samples_estimate(e->encoder.ogg.stream, e->total_samples_to_encode);
-                       OggFLAC__stream_encoder_set_metadata(e->encoder.ogg.stream, (num_metadata > 0)? metadata : 0, num_metadata);
-                       OggFLAC__stream_encoder_set_write_callback(e->encoder.ogg.stream, ogg_stream_encoder_write_callback);
-                       OggFLAC__stream_encoder_set_metadata_callback(e->encoder.ogg.stream, ogg_stream_encoder_metadata_callback);
-                       OggFLAC__stream_encoder_set_client_data(e->encoder.ogg.stream, e);
-
-                       OggFLAC__stream_encoder_disable_constant_subframes(e->encoder.ogg.stream, options.debug.disable_constant_subframes);
-                       OggFLAC__stream_encoder_disable_fixed_subframes(e->encoder.ogg.stream, options.debug.disable_fixed_subframes);
-                       OggFLAC__stream_encoder_disable_verbatim_subframes(e->encoder.ogg.stream, options.debug.disable_verbatim_subframes);
-
-                       if(OggFLAC__stream_encoder_init(e->encoder.ogg.stream) != FLAC__STREAM_ENCODER_OK) {
-                               print_error_with_state(e, "ERROR initializing encoder");
-                               if(0 != cuesheet)
-                                       FLAC__metadata_object_delete(cuesheet);
-                               return false;
-                       }
-               }
-               else {
-                       OggFLAC__file_encoder_set_serial_number(e->encoder.ogg.file, options.serial_number);
-                       OggFLAC__file_encoder_set_filename(e->encoder.ogg.file, e->outfilename);
-                       OggFLAC__file_encoder_set_verify(e->encoder.ogg.file, options.verify);
-                       OggFLAC__file_encoder_set_streamable_subset(e->encoder.ogg.file, !options.lax);
-                       OggFLAC__file_encoder_set_do_mid_side_stereo(e->encoder.ogg.file, options.do_mid_side);
-                       OggFLAC__file_encoder_set_loose_mid_side_stereo(e->encoder.ogg.file, options.loose_mid_side);
-                       OggFLAC__file_encoder_set_channels(e->encoder.ogg.file, channels);
-                       OggFLAC__file_encoder_set_bits_per_sample(e->encoder.ogg.file, bps);
-                       OggFLAC__file_encoder_set_sample_rate(e->encoder.ogg.file, sample_rate);
-                       OggFLAC__file_encoder_set_blocksize(e->encoder.ogg.file, options.blocksize);
-                       OggFLAC__file_encoder_set_apodization(e->encoder.ogg.file, options.apodizations);
-                       OggFLAC__file_encoder_set_max_lpc_order(e->encoder.ogg.file, options.max_lpc_order);
-                       OggFLAC__file_encoder_set_qlp_coeff_precision(e->encoder.ogg.file, options.qlp_coeff_precision);
-                       OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(e->encoder.ogg.file, options.do_qlp_coeff_prec_search);
-                       OggFLAC__file_encoder_set_do_escape_coding(e->encoder.ogg.file, options.do_escape_coding);
-                       OggFLAC__file_encoder_set_do_exhaustive_model_search(e->encoder.ogg.file, options.do_exhaustive_model_search);
-                       OggFLAC__file_encoder_set_min_residual_partition_order(e->encoder.ogg.file, options.min_residual_partition_order);
-                       OggFLAC__file_encoder_set_max_residual_partition_order(e->encoder.ogg.file, options.max_residual_partition_order);
-                       OggFLAC__file_encoder_set_rice_parameter_search_dist(e->encoder.ogg.file, options.rice_parameter_search_dist);
-                       OggFLAC__file_encoder_set_total_samples_estimate(e->encoder.ogg.file, e->total_samples_to_encode);
-                       OggFLAC__file_encoder_set_metadata(e->encoder.ogg.file, (num_metadata > 0)? metadata : 0, num_metadata);
-                       OggFLAC__file_encoder_set_progress_callback(e->encoder.ogg.file, ogg_file_encoder_progress_callback);
-                       OggFLAC__file_encoder_set_client_data(e->encoder.ogg.file, e);
-
-                       OggFLAC__file_encoder_disable_constant_subframes(e->encoder.ogg.file, options.debug.disable_constant_subframes);
-                       OggFLAC__file_encoder_disable_fixed_subframes(e->encoder.ogg.file, options.debug.disable_fixed_subframes);
-                       OggFLAC__file_encoder_disable_verbatim_subframes(e->encoder.ogg.file, options.debug.disable_verbatim_subframes);
-
-                       if(OggFLAC__file_encoder_init(e->encoder.ogg.file) != OggFLAC__FILE_ENCODER_OK) {
-                               print_error_with_state(e, "ERROR initializing encoder");
-                               if(0 != cuesheet)
-                                       FLAC__metadata_object_delete(cuesheet);
-                               return false;
-                       }
-               }
-       }
-       else
-#endif
-       if(e->is_stdout) {
-               FLAC__stream_encoder_set_verify(e->encoder.flac.stream, options.verify);
-               FLAC__stream_encoder_set_streamable_subset(e->encoder.flac.stream, !options.lax);
-               FLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.flac.stream, options.do_mid_side);
-               FLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder.flac.stream, options.loose_mid_side);
-               FLAC__stream_encoder_set_channels(e->encoder.flac.stream, channels);
-               FLAC__stream_encoder_set_bits_per_sample(e->encoder.flac.stream, bps);
-               FLAC__stream_encoder_set_sample_rate(e->encoder.flac.stream, sample_rate);
-               FLAC__stream_encoder_set_blocksize(e->encoder.flac.stream, options.blocksize);
-               FLAC__stream_encoder_set_apodization(e->encoder.flac.stream, options.apodizations);
-               FLAC__stream_encoder_set_max_lpc_order(e->encoder.flac.stream, options.max_lpc_order);
-               FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.flac.stream, options.qlp_coeff_precision);
-               FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac.stream, options.do_qlp_coeff_prec_search);
-               FLAC__stream_encoder_set_do_escape_coding(e->encoder.flac.stream, options.do_escape_coding);
-               FLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder.flac.stream, options.do_exhaustive_model_search);
-               FLAC__stream_encoder_set_min_residual_partition_order(e->encoder.flac.stream, options.min_residual_partition_order);
-               FLAC__stream_encoder_set_max_residual_partition_order(e->encoder.flac.stream, options.max_residual_partition_order);
-               FLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder.flac.stream, options.rice_parameter_search_dist);
-               FLAC__stream_encoder_set_total_samples_estimate(e->encoder.flac.stream, e->total_samples_to_encode);
-               FLAC__stream_encoder_set_metadata(e->encoder.flac.stream, (num_metadata > 0)? metadata : 0, num_metadata);
-               FLAC__stream_encoder_set_write_callback(e->encoder.flac.stream, flac_stream_encoder_write_callback);
-               FLAC__stream_encoder_set_metadata_callback(e->encoder.flac.stream, flac_stream_encoder_metadata_callback);
-               FLAC__stream_encoder_set_client_data(e->encoder.flac.stream, e);
-
-               FLAC__stream_encoder_disable_constant_subframes(e->encoder.flac.stream, options.debug.disable_constant_subframes);
-               FLAC__stream_encoder_disable_fixed_subframes(e->encoder.flac.stream, options.debug.disable_fixed_subframes);
-               FLAC__stream_encoder_disable_verbatim_subframes(e->encoder.flac.stream, options.debug.disable_verbatim_subframes);
-
-               if(FLAC__stream_encoder_init(e->encoder.flac.stream) != FLAC__STREAM_ENCODER_OK) {
-                       print_error_with_state(e, "ERROR initializing encoder");
+               OggFLAC__stream_encoder_set_serial_number(e->encoder.ogg, options.serial_number);
+               OggFLAC__stream_encoder_set_verify(e->encoder.ogg, options.verify);
+               OggFLAC__stream_encoder_set_streamable_subset(e->encoder.ogg, !options.lax);
+               OggFLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.ogg, options.do_mid_side);
+               OggFLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder.ogg, options.loose_mid_side);
+               OggFLAC__stream_encoder_set_channels(e->encoder.ogg, channels);
+               OggFLAC__stream_encoder_set_bits_per_sample(e->encoder.ogg, bps);
+               OggFLAC__stream_encoder_set_sample_rate(e->encoder.ogg, sample_rate);
+               OggFLAC__stream_encoder_set_blocksize(e->encoder.ogg, options.blocksize);
+               OggFLAC__stream_encoder_set_apodization(e->encoder.ogg, options.apodizations);
+               OggFLAC__stream_encoder_set_max_lpc_order(e->encoder.ogg, options.max_lpc_order);
+               OggFLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.ogg, options.qlp_coeff_precision);
+               OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.ogg, options.do_qlp_coeff_prec_search);
+               OggFLAC__stream_encoder_set_do_escape_coding(e->encoder.ogg, options.do_escape_coding);
+               OggFLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder.ogg, options.do_exhaustive_model_search);
+               OggFLAC__stream_encoder_set_min_residual_partition_order(e->encoder.ogg, options.min_residual_partition_order);
+               OggFLAC__stream_encoder_set_max_residual_partition_order(e->encoder.ogg, options.max_residual_partition_order);
+               OggFLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder.ogg, options.rice_parameter_search_dist);
+               OggFLAC__stream_encoder_set_total_samples_estimate(e->encoder.ogg, e->total_samples_to_encode);
+               OggFLAC__stream_encoder_set_metadata(e->encoder.ogg, (num_metadata > 0)? metadata : 0, num_metadata);
+
+               OggFLAC__stream_encoder_disable_constant_subframes(e->encoder.ogg, options.debug.disable_constant_subframes);
+               OggFLAC__stream_encoder_disable_fixed_subframes(e->encoder.ogg, options.debug.disable_fixed_subframes);
+               OggFLAC__stream_encoder_disable_verbatim_subframes(e->encoder.ogg, options.debug.disable_verbatim_subframes);
+
+               init_status = OggFLAC__stream_encoder_init_file(e->encoder.ogg, e->is_stdout? 0 : e->outfilename, encoder_progress_callback, /*client_data=*/e);
+               if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
+                       print_error_with_init_status(e, "ERROR initializing encoder", init_status);
                        if(0 != cuesheet)
                                FLAC__metadata_object_delete(cuesheet);
                        return false;
                }
        }
-       else {
-               FLAC__file_encoder_set_filename(e->encoder.flac.file, e->outfilename);
-               FLAC__file_encoder_set_verify(e->encoder.flac.file, options.verify);
-               FLAC__file_encoder_set_streamable_subset(e->encoder.flac.file, !options.lax);
-               FLAC__file_encoder_set_do_mid_side_stereo(e->encoder.flac.file, options.do_mid_side);
-               FLAC__file_encoder_set_loose_mid_side_stereo(e->encoder.flac.file, options.loose_mid_side);
-               FLAC__file_encoder_set_channels(e->encoder.flac.file, channels);
-               FLAC__file_encoder_set_bits_per_sample(e->encoder.flac.file, bps);
-               FLAC__file_encoder_set_sample_rate(e->encoder.flac.file, sample_rate);
-               FLAC__file_encoder_set_blocksize(e->encoder.flac.file, options.blocksize);
-               FLAC__file_encoder_set_apodization(e->encoder.flac.file, options.apodizations);
-               FLAC__file_encoder_set_max_lpc_order(e->encoder.flac.file, options.max_lpc_order);
-               FLAC__file_encoder_set_qlp_coeff_precision(e->encoder.flac.file, options.qlp_coeff_precision);
-               FLAC__file_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac.file, options.do_qlp_coeff_prec_search);
-               FLAC__file_encoder_set_do_escape_coding(e->encoder.flac.file, options.do_escape_coding);
-               FLAC__file_encoder_set_do_exhaustive_model_search(e->encoder.flac.file, options.do_exhaustive_model_search);
-               FLAC__file_encoder_set_min_residual_partition_order(e->encoder.flac.file, options.min_residual_partition_order);
-               FLAC__file_encoder_set_max_residual_partition_order(e->encoder.flac.file, options.max_residual_partition_order);
-               FLAC__file_encoder_set_rice_parameter_search_dist(e->encoder.flac.file, options.rice_parameter_search_dist);
-               FLAC__file_encoder_set_total_samples_estimate(e->encoder.flac.file, e->total_samples_to_encode);
-               FLAC__file_encoder_set_metadata(e->encoder.flac.file, (num_metadata > 0)? metadata : 0, num_metadata);
-               FLAC__file_encoder_set_progress_callback(e->encoder.flac.file, flac_file_encoder_progress_callback);
-               FLAC__file_encoder_set_client_data(e->encoder.flac.file, e);
-
-               FLAC__file_encoder_disable_constant_subframes(e->encoder.flac.file, options.debug.disable_constant_subframes);
-               FLAC__file_encoder_disable_fixed_subframes(e->encoder.flac.file, options.debug.disable_fixed_subframes);
-               FLAC__file_encoder_disable_verbatim_subframes(e->encoder.flac.file, options.debug.disable_verbatim_subframes);
-
-               if(FLAC__file_encoder_init(e->encoder.flac.file) != FLAC__FILE_ENCODER_OK) {
-                       print_error_with_state(e, "ERROR initializing encoder");
+       else
+#endif
+       {
+               FLAC__stream_encoder_set_verify(e->encoder.flac, options.verify);
+               FLAC__stream_encoder_set_streamable_subset(e->encoder.flac, !options.lax);
+               FLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.flac, options.do_mid_side);
+               FLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder.flac, options.loose_mid_side);
+               FLAC__stream_encoder_set_channels(e->encoder.flac, channels);
+               FLAC__stream_encoder_set_bits_per_sample(e->encoder.flac, bps);
+               FLAC__stream_encoder_set_sample_rate(e->encoder.flac, sample_rate);
+               FLAC__stream_encoder_set_blocksize(e->encoder.flac, options.blocksize);
+               FLAC__stream_encoder_set_apodization(e->encoder.flac, options.apodizations);
+               FLAC__stream_encoder_set_max_lpc_order(e->encoder.flac, options.max_lpc_order);
+               FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder.flac, options.qlp_coeff_precision);
+               FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder.flac, options.do_qlp_coeff_prec_search);
+               FLAC__stream_encoder_set_do_escape_coding(e->encoder.flac, options.do_escape_coding);
+               FLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder.flac, options.do_exhaustive_model_search);
+               FLAC__stream_encoder_set_min_residual_partition_order(e->encoder.flac, options.min_residual_partition_order);
+               FLAC__stream_encoder_set_max_residual_partition_order(e->encoder.flac, options.max_residual_partition_order);
+               FLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder.flac, options.rice_parameter_search_dist);
+               FLAC__stream_encoder_set_total_samples_estimate(e->encoder.flac, e->total_samples_to_encode);
+               FLAC__stream_encoder_set_metadata(e->encoder.flac, (num_metadata > 0)? metadata : 0, num_metadata);
+
+               FLAC__stream_encoder_disable_constant_subframes(e->encoder.flac, options.debug.disable_constant_subframes);
+               FLAC__stream_encoder_disable_fixed_subframes(e->encoder.flac, options.debug.disable_fixed_subframes);
+               FLAC__stream_encoder_disable_verbatim_subframes(e->encoder.flac, options.debug.disable_verbatim_subframes);
+
+               init_status = FLAC__stream_encoder_init_file(e->encoder.flac, e->is_stdout? 0 : e->outfilename, encoder_progress_callback, /*client_data=*/e);
+               if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
+                       print_error_with_init_status(e, "ERROR initializing encoder", init_status);
                        if(0 != cuesheet)
                                FLAC__metadata_object_delete(cuesheet);
                        return false;
@@ -1952,22 +1782,11 @@ FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const b
        }
 
 #ifdef FLAC__HAS_OGG
-       if(e->use_ogg) {
-               if(e->is_stdout) {
-                       return OggFLAC__stream_encoder_process(e->encoder.ogg.stream, buffer, samples);
-               }
-               else {
-                       return OggFLAC__file_encoder_process(e->encoder.ogg.file, buffer, samples);
-               }
-       }
+       if(e->use_ogg)
+               return OggFLAC__stream_encoder_process(e->encoder.ogg, buffer, samples);
        else
 #endif
-       if(e->is_stdout) {
-               return FLAC__stream_encoder_process(e->encoder.flac.stream, buffer, samples);
-       }
-       else {
-               return FLAC__file_encoder_process(e->encoder.flac.file, buffer, samples);
-       }
+       return FLAC__stream_encoder_process(e->encoder.flac, buffer, samples);
 }
 
 FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e)
@@ -2128,38 +1947,7 @@ void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_
        }
 }
 
-#ifdef FLAC__HAS_OGG
-FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       EncoderSession *encoder_session = (EncoderSession*)client_data;
-
-       (void)encoder;
-
-       encoder_session->bytes_written += bytes;
-       /*
-        * With Ogg FLAC we don't get one write callback per frame and
-        * we don't have a good number for 'samples', so we estimate based
-        * on the frame number and the knowledge that all blocks (except
-        * the last) are the same size.
-        */
-       (void)samples;
-       encoder_session->samples_written = (current_frame+1) * encoder_session->blocksize;
-
-       if(encoder_session->total_samples_to_encode > 0 && !(current_frame & encoder_session->stats_mask))
-               print_stats(encoder_session);
-
-       if(flac__utils_fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_session->fout) == bytes)
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-       else
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
-}
-
-void ogg_stream_encoder_metadata_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       // do nothing, for compatibilty.  soon we will be using the ogg file encoder anyway.
-       (void)encoder, (void)metadata, (void)client_data;
-}
-
+#if 0 /*@@@@@@ old ogg progress callback, I don't think the comment about samples_written is true anymore but keep around until verified */
 void ogg_file_encoder_progress_callback(const OggFLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
 {
        EncoderSession *encoder_session = (EncoderSession*)client_data;
@@ -2177,34 +1965,7 @@ void ogg_file_encoder_progress_callback(const OggFLAC__FileEncoder *encoder, FLA
 
 #endif
 
-FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       EncoderSession *encoder_session = (EncoderSession*)client_data;
-
-       (void)encoder;
-
-       encoder_session->bytes_written += bytes;
-       encoder_session->samples_written += samples;
-
-       if(samples && encoder_session->total_samples_to_encode > 0 && !(current_frame & encoder_session->stats_mask))
-               print_stats(encoder_session);
-
-       if(flac__utils_fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_session->fout) == bytes)
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-       else
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
-}
-
-void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       /*
-        * Nothing to do; if we get here, we're decoding to stdout, in
-        * which case we can't seek backwards to write new metadata.
-        */
-       (void)encoder, (void)metadata, (void)client_data;
-}
-
-void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
+void encoder_progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
 {
        EncoderSession *encoder_session = (EncoderSession*)client_data;
 
@@ -2217,14 +1978,14 @@ void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC_
                print_stats(encoder_session);
 }
 
-FLAC__SeekableStreamDecoderReadStatus flac_decoder_read_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+FLAC__StreamDecoderReadStatus flac_decoder_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
 {
        size_t n = 0;
        FLACDecoderData *data = (FLACDecoderData*)client_data;
        (void)decoder;
 
        if (data->fatal_error)
-               return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
+               return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
 
        /* use up lookahead first */
        if (data->lookahead_length) {
@@ -2238,51 +1999,51 @@ FLAC__SeekableStreamDecoderReadStatus flac_decoder_read_callback(const FLAC__See
        /* get the rest from file */
        if (*bytes > n) {
                *bytes = n + fread(buffer, 1, *bytes-n, data->encoder_session->fin);
-               return ferror(data->encoder_session->fin)? FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR : FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
+               return ferror(data->encoder_session->fin)? FLAC__STREAM_DECODER_READ_STATUS_ABORT : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
        }
        else
-               return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
+               return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
 }
 
-FLAC__SeekableStreamDecoderSeekStatus flac_decoder_seek_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+FLAC__StreamDecoderSeekStatus flac_decoder_seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
 {
        FLACDecoderData *data = (FLACDecoderData*)client_data;
        (void)decoder;
 
        if(fseeko(data->encoder_session->fin, (off_t)absolute_byte_offset, SEEK_SET) < 0)
-               return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
        else
-               return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
+               return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
 }
 
-FLAC__SeekableStreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+FLAC__StreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
 {
        FLACDecoderData *data = (FLACDecoderData*)client_data;
        off_t pos;
        (void)decoder;
 
        if((pos = ftello(data->encoder_session->fin)) < 0)
-               return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
        else {
                *absolute_byte_offset = (FLAC__uint64)pos;
-               return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
+               return FLAC__STREAM_DECODER_TELL_STATUS_OK;
        }
 }
 
-FLAC__SeekableStreamDecoderLengthStatus flac_decoder_length_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
+FLAC__StreamDecoderLengthStatus flac_decoder_length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
 {
        FLACDecoderData *data = (FLACDecoderData*)client_data;
        (void)decoder;
 
        if(0 == data->filesize)
-               return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
        else {
                *stream_length = (FLAC__uint64)data->filesize;
-               return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
        }
 }
 
-FLAC__bool flac_decoder_eof_callback(const FLAC__SeekableStreamDecoder *decoder, void *client_data)
+FLAC__bool flac_decoder_eof_callback(const FLAC__StreamDecoder *decoder, void *client_data)
 {
        FLACDecoderData *data = (FLACDecoderData*)client_data;
        (void)decoder;
@@ -2290,13 +2051,13 @@ FLAC__bool flac_decoder_eof_callback(const FLAC__SeekableStreamDecoder *decoder,
        return feof(data->encoder_session->fin)? true : false;
 }
 
-FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
        FLACDecoderData *data = (FLACDecoderData*)client_data;
        FLAC__uint64 n = min(data->samples_left_to_process, frame->header.blocksize);
        (void)decoder;
 
-       if(!EncoderSession_process(data->encoder_session, buffer, n)) {
+       if(!EncoderSession_process(data->encoder_session, buffer, (unsigned)n)) {
                print_error_with_state(data->encoder_session, "ERROR during encoding");
                data->fatal_error = true;
                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
@@ -2306,7 +2067,7 @@ FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__SeekableS
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
 
-void flac_decoder_metadata_callback(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+void flac_decoder_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        FLACDecoderData *data = (FLACDecoderData*)client_data;
        (void)decoder;
@@ -2323,7 +2084,7 @@ void flac_decoder_metadata_callback(const FLAC__SeekableStreamDecoder *decoder,
                data->num_metadata_blocks++;
 }
 
-void flac_decoder_error_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+void flac_decoder_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
        FLACDecoderData *data = (FLACDecoderData*)client_data;
        (void)decoder;
@@ -2400,35 +2161,52 @@ void print_stats(const EncoderSession *encoder_session)
        }
 }
 
-void print_error_with_state(const EncoderSession *e, const char *message)
+void print_error_with_init_status(const EncoderSession *e, const char *message, FLAC__StreamEncoderInitStatus init_status)
 {
        const int ilen = strlen(e->inbasefilename) + 1;
-       const char *state_string;
+       const char *state_string = "";
 
        flac__utils_printf(stderr, 1, "\n%s: %s\n", e->inbasefilename, message);
 
+       flac__utils_printf(stderr, 1, "%*s init_status = %s\n", ilen, "", FLAC__StreamEncoderInitStatusString[init_status]);
+
+       if(init_status == FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR) {
 #ifdef FLAC__HAS_OGG
-       if(e->use_ogg) {
-               if(e->is_stdout) {
-                       state_string = OggFLAC__stream_encoder_get_resolved_state_string(e->encoder.ogg.stream);
-               }
-               else {
-                       state_string = OggFLAC__file_encoder_get_resolved_state_string(e->encoder.ogg.file);
-               }
-       }
-       else
+               if(e->use_ogg)
+                       state_string = OggFLAC__stream_encoder_get_resolved_state_string(e->encoder.ogg);
+               else
 #endif
-       if(e->is_stdout) {
-               state_string = FLAC__stream_encoder_get_resolved_state_string(e->encoder.flac.stream);
-       }
-       else {
-               state_string = FLAC__file_encoder_get_resolved_state_string(e->encoder.flac.file);
-       }
+               state_string = FLAC__stream_encoder_get_resolved_state_string(e->encoder.flac);
 
-       flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", state_string);
+               flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", state_string);
 
-       /* print out some more info for some errors: */
-       if(0 == strcmp(state_string, FLAC__StreamEncoderStateString[FLAC__STREAM_ENCODER_NOT_STREAMABLE])) {
+               /* print out some more info for some errors: */
+               if(
+                       0 == strcmp(state_string, FLAC__StreamEncoderStateString[FLAC__STREAM_ENCODER_CLIENT_ERROR])
+#ifdef FLAC__HAS_OGG
+                       || 0 == strcmp(state_string, OggFLAC__StreamEncoderStateString[OggFLAC__STREAM_ENCODER_CLIENT_ERROR])
+#endif
+               ) {
+                       flac__utils_printf(stderr, 1,
+                               "\n"
+                               "An error occurred while writing; the most common cause is that the disk is full.\n"
+                       );
+               }
+               else if(
+                       0 == strcmp(state_string, FLAC__StreamEncoderStateString[FLAC__STREAM_ENCODER_IO_ERROR])
+#ifdef FLAC__HAS_OGG
+                       || 0 == strcmp(state_string, OggFLAC__StreamEncoderStateString[OggFLAC__STREAM_ENCODER_IO_ERROR])
+#endif
+               ) {
+                       flac__utils_printf(stderr, 1,
+                               "\n"
+                               "An error occurred opening the output file; it is likely that the output\n"
+                               "directory does not exist or is not writable, the output file already exists and\n"
+                               "is not writable, or the disk is full.\n"
+                       );
+               }
+       }
+       else if(init_status == FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE) {
                flac__utils_printf(stderr, 1,
                        "\n"
                        "The encoding parameters specified do not conform to the FLAC Subset and may not\n"
@@ -2436,28 +2214,34 @@ void print_error_with_state(const EncoderSession *e, const char *message)
                        "options to encode with these parameters anyway.\n"
                );
        }
-       else if(
-               0 == strcmp(state_string, FLAC__FileEncoderStateString[FLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING])
+}
+
+void print_error_with_state(const EncoderSession *e, const char *message)
+{
+       const int ilen = strlen(e->inbasefilename) + 1;
+       const char *state_string;
+
+       flac__utils_printf(stderr, 1, "\n%s: %s\n", e->inbasefilename, message);
+
 #ifdef FLAC__HAS_OGG
-               || 0 == strcmp(state_string, OggFLAC__FileEncoderStateString[OggFLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING])
+       if(e->use_ogg)
+               state_string = OggFLAC__stream_encoder_get_resolved_state_string(e->encoder.ogg);
+       else
 #endif
-       ) {
-               flac__utils_printf(stderr, 1,
-                       "\n"
-                       "An error occurred while writing; the most common cause is that the disk is full.\n"
-               );
-       }
-       else if(
-               0 == strcmp(state_string, FLAC__FileEncoderStateString[FLAC__FILE_ENCODER_ERROR_OPENING_FILE])
+       state_string = FLAC__stream_encoder_get_resolved_state_string(e->encoder.flac);
+
+       flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", state_string);
+
+       /* print out some more info for some errors: */
+       if(
+               0 == strcmp(state_string, FLAC__StreamEncoderStateString[FLAC__STREAM_ENCODER_CLIENT_ERROR])
 #ifdef FLAC__HAS_OGG
-               || 0 == strcmp(state_string, OggFLAC__FileEncoderStateString[OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE])
+               || 0 == strcmp(state_string, OggFLAC__StreamEncoderStateString[OggFLAC__STREAM_ENCODER_CLIENT_ERROR])
 #endif
        ) {
                flac__utils_printf(stderr, 1,
                        "\n"
-                       "An error occurred opening the output file; it is likely that the output\n"
-                       "directory does not exist or is not writable, the output file already exists and\n"
-                       "is not writable, or the disk is full.\n"
+                       "An error occurred while writing; the most common cause is that the disk is full.\n"
                );
        }
 }
@@ -2472,22 +2256,11 @@ void print_verify_error(EncoderSession *e)
        FLAC__int32 got;
 
 #ifdef FLAC__HAS_OGG
-       if(e->use_ogg) {
-               if(e->is_stdout) {
-                       OggFLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder.ogg.stream, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               }
-               else {
-                       OggFLAC__file_encoder_get_verify_decoder_error_stats(e->encoder.ogg.file, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               }
-       }
+       if(e->use_ogg)
+               OggFLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder.ogg, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
        else
 #endif
-       if(e->is_stdout) {
-               FLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder.flac.stream, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-       }
-       else {
-               FLAC__file_encoder_get_verify_decoder_error_stats(e->encoder.flac.file, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-       }
+       FLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder.flac, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
 
        flac__utils_printf(stderr, 1, "%s: ERROR: mismatch in decoded data, verify FAILED!\n", e->inbasefilename);
        flac__utils_printf(stderr, 1, "       Absolute sample=%u, frame=%u, channel=%u, sample=%u, expected %d, got %d\n", (unsigned)absolute_sample, frame_number, channel, sample, expected, got);
index 07e9864..d06d1f0 100644 (file)
@@ -1026,15 +1026,21 @@ int parse_option(int short_option, const char *long_option, const char *option_a
                                break;
                        case 'S':
                                FLAC__ASSERT(0 != option_argument);
-                               if(option_values.num_requested_seek_points < 0)
+                               if(0 == strcmp(option_argument, "-")) {
                                        option_values.num_requested_seek_points = 0;
-                               option_values.num_requested_seek_points++;
-                               if(strlen(option_values.requested_seek_points)+strlen(option_argument)+2 >= sizeof(option_values.requested_seek_points)) {
-                                       return usage_error("ERROR: too many seekpoints requested\n");
+                                       option_values.requested_seek_points[0] = '\0';
                                }
                                else {
-                                       strcat(option_values.requested_seek_points, option_argument);
-                                       strcat(option_values.requested_seek_points, ";");
+                                       if(option_values.num_requested_seek_points < 0)
+                                               option_values.num_requested_seek_points = 0;
+                                       option_values.num_requested_seek_points++;
+                                       if(strlen(option_values.requested_seek_points)+strlen(option_argument)+2 >= sizeof(option_values.requested_seek_points)) {
+                                               return usage_error("ERROR: too many seekpoints requested\n");
+                                       }
+                                       else {
+                                               strcat(option_values.requested_seek_points, option_argument);
+                                               strcat(option_values.requested_seek_points, ";");
+                                       }
                                }
                                break;
                        case 'P':
index deb50c4..a9d04c8 100644 (file)
@@ -47,7 +47,5 @@ libFLAC___la_SOURCES = \
        file_decoder.cpp \
        file_encoder.cpp \
        metadata.cpp \
-       seekable_stream_decoder.cpp \
-       seekable_stream_encoder.cpp \
        stream_decoder.cpp \
        stream_encoder.cpp
index 942b1e1..73f7ce2 100644 (file)
@@ -41,8 +41,6 @@ SRCS_CPP = \
        file_decoder.cpp \
        file_encoder.cpp \
        metadata.cpp \
-       seekable_stream_decoder.cpp \
-       seekable_stream_encoder.cpp \
        stream_decoder.cpp \
        stream_encoder.cpp
 
index 597e251..8281428 100644 (file)
@@ -41,195 +41,40 @@ namespace FLAC {
        namespace Decoder {
 
                File::File():
-               decoder_(::FLAC__file_decoder_new())
+                       Stream()
                { }
 
                File::~File()
                {
-                       if(0 != decoder_) {
-                               (void) ::FLAC__file_decoder_finish(decoder_);
-                               ::FLAC__file_decoder_delete(decoder_);
-                       }
                }
 
-               bool File::is_valid() const
-               {
-                       return 0 != decoder_;
-               }
-
-               bool File::set_md5_checking(bool value)
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_set_md5_checking(decoder_, value);
-               }
-
-               bool File::set_filename(const char *value)
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_set_filename(decoder_, value);
-               }
-
-               bool File::set_metadata_respond(::FLAC__MetadataType type)
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_set_metadata_respond(decoder_, type);
-               }
-
-               bool File::set_metadata_respond_application(const FLAC__byte id[4])
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_set_metadata_respond_application(decoder_, id);
-               }
-
-               bool File::set_metadata_respond_all()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_set_metadata_respond_all(decoder_);
-               }
-
-               bool File::set_metadata_ignore(::FLAC__MetadataType type)
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_set_metadata_ignore(decoder_, type);
-               }
-
-               bool File::set_metadata_ignore_application(const FLAC__byte id[4])
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_set_metadata_ignore_application(decoder_, id);
-               }
-
-               bool File::set_metadata_ignore_all()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_set_metadata_ignore_all(decoder_);
-               }
-
-               File::State File::get_state() const
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return State(::FLAC__file_decoder_get_state(decoder_));
-               }
-
-               SeekableStream::State File::get_seekable_stream_decoder_state() const
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return SeekableStream::State(::FLAC__file_decoder_get_seekable_stream_decoder_state(decoder_));
-               }
-
-               Stream::State File::get_stream_decoder_state() const
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return Stream::State(::FLAC__file_decoder_get_stream_decoder_state(decoder_));
-               }
-
-               bool File::get_md5_checking() const
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_get_md5_checking(decoder_);
-               }
-
-               unsigned File::get_channels() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_decoder_get_channels(decoder_);
-               }
-
-               ::FLAC__ChannelAssignment File::get_channel_assignment() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_decoder_get_channel_assignment(decoder_);
-               }
-
-               unsigned File::get_bits_per_sample() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_decoder_get_bits_per_sample(decoder_);
-               }
-
-               unsigned File::get_sample_rate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_decoder_get_sample_rate(decoder_);
-               }
-
-               unsigned File::get_blocksize() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_decoder_get_blocksize(decoder_);
-               }
-
-               File::State File::init()
+               ::FLAC__StreamDecoderInitStatus File::init(FILE *file)
                {
                        FLAC__ASSERT(0 != decoder_);
-                       ::FLAC__file_decoder_set_write_callback(decoder_, write_callback_);
-                       ::FLAC__file_decoder_set_metadata_callback(decoder_, metadata_callback_);
-                       ::FLAC__file_decoder_set_error_callback(decoder_, error_callback_);
-                       ::FLAC__file_decoder_set_client_data(decoder_, (void*)this);
-                       return State(::FLAC__file_decoder_init(decoder_));
+                       return ::FLAC__stream_decoder_init_FILE(decoder_, file, write_callback_, metadata_callback_, error_callback_, /*client_data=*/(void*)this);
                }
 
-               bool File::finish()
+               ::FLAC__StreamDecoderInitStatus File::init(const char *filename)
                {
                        FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_finish(decoder_);
-               }
-
-               bool File::process_single()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_process_single(decoder_);
-               }
-
-               bool File::process_until_end_of_metadata()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_process_until_end_of_metadata(decoder_);
-               }
-
-               bool File::process_until_end_of_file()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_process_until_end_of_file(decoder_);
-               }
-
-               bool File::skip_single_frame()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_decoder_skip_single_frame(decoder_);
-               }
-
-               bool File::seek_absolute(FLAC__uint64 sample)
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::FLAC__file_decoder_seek_absolute(decoder_, sample);
-               }
-
-               ::FLAC__StreamDecoderWriteStatus File::write_callback_(const ::FLAC__FileDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       File *instance = reinterpret_cast<File *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->write_callback(frame, buffer);
+                       return ::FLAC__stream_decoder_init_file(decoder_, filename, write_callback_, metadata_callback_, error_callback_, /*client_data=*/(void*)this);
                }
 
-               void File::metadata_callback_(const ::FLAC__FileDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
+               ::FLAC__StreamDecoderInitStatus File::init(const std::string &filename)
                {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       File *instance = reinterpret_cast<File *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       instance->metadata_callback(metadata);
+                       return init(filename.c_str());
                }
 
-               void File::error_callback_(const ::FLAC__FileDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data)
+               // This is a dummy to satisfy the pure virtual from Stream; the
+               // read callback will never be called since we are initializing
+               // with FLAC__stream_decoder_init_FILE() or
+               // FLAC__stream_decoder_init_file() and those supply the read
+               // callback internally.
+               ::FLAC__StreamDecoderReadStatus File::read_callback(FLAC__byte buffer[], unsigned *bytes)
                {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       File *instance = reinterpret_cast<File *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       instance->error_callback(status);
+                       (void)buffer, (void)bytes;
+                       FLAC__ASSERT(false);
+                       return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; // double protection
                }
 
        }
index a3d6e57..89a4164 100644 (file)
@@ -41,323 +41,40 @@ namespace FLAC {
        namespace Encoder {
 
                File::File():
-               encoder_(::FLAC__file_encoder_new())
+                       Stream()
                { }
 
                File::~File()
                {
-                       if(0 != encoder_) {
-                               ::FLAC__file_encoder_finish(encoder_);
-                               ::FLAC__file_encoder_delete(encoder_);
-                       }
                }
 
-               bool File::is_valid() const
-               {
-                       return 0 != encoder_;
-               }
-
-               bool File::set_verify(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_verify(encoder_, value);
-               }
-
-               bool File::set_streamable_subset(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_streamable_subset(encoder_, value);
-               }
-
-               bool File::set_do_mid_side_stereo(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_do_mid_side_stereo(encoder_, value);
-               }
-
-               bool File::set_loose_mid_side_stereo(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_loose_mid_side_stereo(encoder_, value);
-               }
-
-               bool File::set_channels(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_channels(encoder_, value);
-               }
-
-               bool File::set_bits_per_sample(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_bits_per_sample(encoder_, value);
-               }
-
-               bool File::set_sample_rate(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_sample_rate(encoder_, value);
-               }
-
-               bool File::set_blocksize(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_blocksize(encoder_, value);
-               }
-
-               bool File::set_apodization(const char *specification)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_apodization(encoder_, specification);
-               }
-
-               bool File::set_max_lpc_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_max_lpc_order(encoder_, value);
-               }
-
-               bool File::set_qlp_coeff_precision(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_qlp_coeff_precision(encoder_, value);
-               }
-
-               bool File::set_do_qlp_coeff_prec_search(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_do_qlp_coeff_prec_search(encoder_, value);
-               }
-
-               bool File::set_do_escape_coding(bool value)
+               ::FLAC__StreamEncoderInitStatus File::init(FILE *file)
                {
                        FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_do_escape_coding(encoder_, value);
+                       return ::FLAC__stream_encoder_init_FILE(encoder_, file, progress_callback_, /*client_data=*/(void*)this);
                }
 
-               bool File::set_do_exhaustive_model_search(bool value)
+               ::FLAC__StreamEncoderInitStatus File::init(const char *filename)
                {
                        FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_do_exhaustive_model_search(encoder_, value);
+                       return ::FLAC__stream_encoder_init_file(encoder_, filename, progress_callback_, /*client_data=*/(void*)this);
                }
 
-               bool File::set_min_residual_partition_order(unsigned value)
+               ::FLAC__StreamEncoderInitStatus File::init(const std::string &filename)
                {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_min_residual_partition_order(encoder_, value);
-               }
-
-               bool File::set_max_residual_partition_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_max_residual_partition_order(encoder_, value);
-               }
-
-               bool File::set_rice_parameter_search_dist(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_rice_parameter_search_dist(encoder_, value);
-               }
-
-               bool File::set_total_samples_estimate(FLAC__uint64 value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_total_samples_estimate(encoder_, value);
-               }
-
-               bool File::set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_metadata(encoder_, metadata, num_blocks);
-               }
-
-               bool File::set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks)
-               {
-                       FLAC__ASSERT(is_valid());
-#if (defined _MSC_VER) || (defined __SUNPRO_CC)
-                       // MSVC++ can't handle:
-                       // ::FLAC__StreamMetadata *m[num_blocks];
-                       // so we do this ugly workaround
-                       ::FLAC__StreamMetadata **m = new ::FLAC__StreamMetadata*[num_blocks];
-#else
-                       ::FLAC__StreamMetadata *m[num_blocks];
-#endif
-                       for(unsigned i = 0; i < num_blocks; i++) {
-                               // we can get away with this since we know the encoder will only correct the is_last flags
-                               m[i] = const_cast< ::FLAC__StreamMetadata*>((::FLAC__StreamMetadata*)metadata[i]);
-                       }
-#if (defined _MSC_VER) || (defined __SUNPRO_CC)
-                       // complete the hack
-                       const bool ok = (bool)::FLAC__file_encoder_set_metadata(encoder_, m, num_blocks);
-                       delete [] m;
-                       return ok;
-#else
-                       return (bool)::FLAC__file_encoder_set_metadata(encoder_, m, num_blocks);
-#endif
-               }
-
-               bool File::set_filename(const char *value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_set_filename(encoder_, value);
-               }
-
-               File::State File::get_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return State(::FLAC__file_encoder_get_state(encoder_));
-               }
-
-               SeekableStream::State File::get_seekable_stream_encoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return SeekableStream::State(::FLAC__file_encoder_get_seekable_stream_encoder_state(encoder_));
-               }
-
-               Stream::State File::get_stream_encoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return Stream::State(::FLAC__file_encoder_get_stream_encoder_state(encoder_));
+                       return init(filename.c_str());
                }
 
-               Decoder::Stream::State File::get_verify_decoder_state() const
+               // This is a dummy to satisfy the pure virtual from Stream; the
+               // read callback will never be called since we are initializing
+               // with FLAC__stream_decoder_init_FILE() or
+               // FLAC__stream_decoder_init_file() and those supply the read
+               // callback internally.
+               ::FLAC__StreamEncoderWriteStatus File::write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame)
                {
-                       FLAC__ASSERT(is_valid());
-                       return Decoder::Stream::State(::FLAC__file_encoder_get_verify_decoder_state(encoder_));
-               }
-
-               void File::get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::FLAC__file_encoder_get_verify_decoder_error_stats(encoder_, absolute_sample, frame_number, channel, sample, expected, got);
-               }
-
-               bool File::get_verify() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_get_verify(encoder_);
-               }
-
-               bool File::get_streamable_subset() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_get_streamable_subset(encoder_);
-               }
-
-               bool File::get_do_mid_side_stereo() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_get_do_mid_side_stereo(encoder_);
-               }
-
-               bool File::get_loose_mid_side_stereo() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_get_loose_mid_side_stereo(encoder_);
-               }
-
-               unsigned File::get_channels() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_channels(encoder_);
-               }
-
-               unsigned File::get_bits_per_sample() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_bits_per_sample(encoder_);
-               }
-
-               unsigned File::get_sample_rate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_sample_rate(encoder_);
-               }
-
-               unsigned File::get_blocksize() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_blocksize(encoder_);
-               }
-
-               unsigned File::get_max_lpc_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_max_lpc_order(encoder_);
-               }
-
-               unsigned File::get_qlp_coeff_precision() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_qlp_coeff_precision(encoder_);
-               }
-
-               bool File::get_do_qlp_coeff_prec_search() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_get_do_qlp_coeff_prec_search(encoder_);
-               }
-
-               bool File::get_do_escape_coding() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_get_do_escape_coding(encoder_);
-               }
-
-               bool File::get_do_exhaustive_model_search() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_get_do_exhaustive_model_search(encoder_);
-               }
-
-               unsigned File::get_min_residual_partition_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_min_residual_partition_order(encoder_);
-               }
-
-               unsigned File::get_max_residual_partition_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_max_residual_partition_order(encoder_);
-               }
-
-               unsigned File::get_rice_parameter_search_dist() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_rice_parameter_search_dist(encoder_);
-               }
-
-               FLAC__uint64 File::get_total_samples_estimate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__file_encoder_get_total_samples_estimate(encoder_);
-               }
-
-               File::State File::init()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::FLAC__file_encoder_set_progress_callback(encoder_, progress_callback_);
-                       ::FLAC__file_encoder_set_client_data(encoder_, (void*)this);
-                       return State(::FLAC__file_encoder_init(encoder_));
-               }
-
-               void File::finish()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::FLAC__file_encoder_finish(encoder_);
-               }
-
-               bool File::process(const FLAC__int32 * const buffer[], unsigned samples)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_process(encoder_, buffer, samples);
-               }
-
-               bool File::process_interleaved(const FLAC__int32 buffer[], unsigned samples)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__file_encoder_process_interleaved(encoder_, buffer, samples);
+                       (void)buffer, (void)bytes, (void)samples, (void)current_frame;
+                       FLAC__ASSERT(false);
+                       return ::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; // double protection
                }
 
                void File::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate)
@@ -365,7 +82,7 @@ namespace FLAC {
                        (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate;
                }
 
-               void File::progress_callback_(const ::FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
+               void File::progress_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
                {
                        (void)encoder;
                        FLAC__ASSERT(0 != client_data);
index 23ecc2a..ce76786 100644 (file)
@@ -104,14 +104,6 @@ SOURCE=.\metadata.cpp
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\seekable_stream_decoder.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\seekable_stream_encoder.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\stream_decoder.cpp\r
 # End Source File\r
 # Begin Source File\r
index e2204fd..2146872 100644 (file)
@@ -97,14 +97,6 @@ SOURCE=.\metadata.cpp
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\seekable_stream_decoder.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\seekable_stream_encoder.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\stream_decoder.cpp\r
 # End Source File\r
 # Begin Source File\r
diff --git a/src/libFLAC++/seekable_stream_decoder.cpp b/src/libFLAC++/seekable_stream_decoder.cpp
deleted file mode 100644 (file)
index dec393f..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-/* libFLAC++ - Free Lossless Audio Codec library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "FLAC++/decoder.h"
-#include "FLAC/assert.h"
-
-#ifdef _MSC_VER
-// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
-#pragma warning ( disable : 4800 )
-#endif
-
-namespace FLAC {
-       namespace Decoder {
-
-               SeekableStream::SeekableStream():
-               decoder_(::FLAC__seekable_stream_decoder_new())
-               { }
-
-               SeekableStream::~SeekableStream()
-               {
-                       if(0 != decoder_) {
-                               (void) ::FLAC__seekable_stream_decoder_finish(decoder_);
-                               ::FLAC__seekable_stream_decoder_delete(decoder_);
-                       }
-               }
-
-               bool SeekableStream::is_valid() const
-               {
-                       return 0 != decoder_;
-               }
-
-               bool SeekableStream::set_md5_checking(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_set_md5_checking(decoder_, value);
-               }
-
-               bool SeekableStream::set_metadata_respond(::FLAC__MetadataType type)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_set_metadata_respond(decoder_, type);
-               }
-
-               bool SeekableStream::set_metadata_respond_application(const FLAC__byte id[4])
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder_, id);
-               }
-
-               bool SeekableStream::set_metadata_respond_all()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder_);
-               }
-
-               bool SeekableStream::set_metadata_ignore(::FLAC__MetadataType type)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_set_metadata_ignore(decoder_, type);
-               }
-
-               bool SeekableStream::set_metadata_ignore_application(const FLAC__byte id[4])
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder_, id);
-               }
-
-               bool SeekableStream::set_metadata_ignore_all()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder_);
-               }
-
-               SeekableStream::State SeekableStream::get_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return State(::FLAC__seekable_stream_decoder_get_state(decoder_));
-               }
-
-               Stream::State SeekableStream::get_stream_decoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return Stream::State(::FLAC__seekable_stream_decoder_get_stream_decoder_state(decoder_));
-               }
-
-               bool SeekableStream::get_md5_checking() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_get_md5_checking(decoder_);
-               }
-
-               unsigned SeekableStream::get_channels() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_decoder_get_channels(decoder_);
-               }
-
-               ::FLAC__ChannelAssignment SeekableStream::get_channel_assignment() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_decoder_get_channel_assignment(decoder_);
-               }
-
-               unsigned SeekableStream::get_bits_per_sample() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_decoder_get_bits_per_sample(decoder_);
-               }
-
-               unsigned SeekableStream::get_sample_rate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_decoder_get_sample_rate(decoder_);
-               }
-
-               unsigned SeekableStream::get_blocksize() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_decoder_get_blocksize(decoder_);
-               }
-
-               SeekableStream::State SeekableStream::init()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::FLAC__seekable_stream_decoder_set_read_callback(decoder_, read_callback_);
-                       ::FLAC__seekable_stream_decoder_set_seek_callback(decoder_, seek_callback_);
-                       ::FLAC__seekable_stream_decoder_set_tell_callback(decoder_, tell_callback_);
-                       ::FLAC__seekable_stream_decoder_set_length_callback(decoder_, length_callback_);
-                       ::FLAC__seekable_stream_decoder_set_eof_callback(decoder_, eof_callback_);
-                       ::FLAC__seekable_stream_decoder_set_write_callback(decoder_, write_callback_);
-                       ::FLAC__seekable_stream_decoder_set_metadata_callback(decoder_, metadata_callback_);
-                       ::FLAC__seekable_stream_decoder_set_error_callback(decoder_, error_callback_);
-                       ::FLAC__seekable_stream_decoder_set_client_data(decoder_, (void*)this);
-                       return State(::FLAC__seekable_stream_decoder_init(decoder_));
-               }
-
-               bool SeekableStream::finish()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_finish(decoder_);
-               }
-
-               bool SeekableStream::flush()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_flush(decoder_);
-               }
-
-               bool SeekableStream::reset()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_reset(decoder_);
-               }
-
-               bool SeekableStream::process_single()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_process_single(decoder_);
-               }
-
-               bool SeekableStream::process_until_end_of_metadata()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder_);
-               }
-
-               bool SeekableStream::process_until_end_of_stream()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder_);
-               }
-
-               bool SeekableStream::skip_single_frame()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_skip_single_frame(decoder_);
-               }
-
-               bool SeekableStream::seek_absolute(FLAC__uint64 sample)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_decoder_seek_absolute(decoder_, sample);
-               }
-
-               ::FLAC__SeekableStreamDecoderReadStatus SeekableStream::read_callback_(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->read_callback(buffer, bytes);
-               }
-
-               ::FLAC__SeekableStreamDecoderSeekStatus SeekableStream::seek_callback_(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->seek_callback(absolute_byte_offset);
-               }
-
-               ::FLAC__SeekableStreamDecoderTellStatus SeekableStream::tell_callback_(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->tell_callback(absolute_byte_offset);
-               }
-
-               ::FLAC__SeekableStreamDecoderLengthStatus SeekableStream::length_callback_(const ::FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->length_callback(stream_length);
-               }
-
-               FLAC__bool SeekableStream::eof_callback_(const ::FLAC__SeekableStreamDecoder *decoder, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->eof_callback();
-               }
-
-               ::FLAC__StreamDecoderWriteStatus SeekableStream::write_callback_(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->write_callback(frame, buffer);
-               }
-
-               void SeekableStream::metadata_callback_(const ::FLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       instance->metadata_callback(metadata);
-               }
-
-               void SeekableStream::error_callback_(const ::FLAC__SeekableStreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       instance->error_callback(status);
-               }
-
-       }
-}
diff --git a/src/libFLAC++/seekable_stream_encoder.cpp b/src/libFLAC++/seekable_stream_encoder.cpp
deleted file mode 100644 (file)
index 69e2f00..0000000
+++ /dev/null
@@ -1,381 +0,0 @@
-/* libFLAC++ - Free Lossless Audio Codec library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "FLAC++/encoder.h"
-#include "FLAC/assert.h"
-
-#ifdef _MSC_VER
-// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
-#pragma warning ( disable : 4800 )
-#endif
-
-namespace FLAC {
-       namespace Encoder {
-
-               SeekableStream::SeekableStream():
-               encoder_(::FLAC__seekable_stream_encoder_new())
-               { }
-
-               SeekableStream::~SeekableStream()
-               {
-                       if(0 != encoder_) {
-                               ::FLAC__seekable_stream_encoder_finish(encoder_);
-                               ::FLAC__seekable_stream_encoder_delete(encoder_);
-                       }
-               }
-
-               bool SeekableStream::is_valid() const
-               {
-                       return 0 != encoder_;
-               }
-
-               bool SeekableStream::set_verify(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_verify(encoder_, value);
-               }
-
-               bool SeekableStream::set_streamable_subset(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_streamable_subset(encoder_, value);
-               }
-
-               bool SeekableStream::set_do_mid_side_stereo(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder_, value);
-               }
-
-               bool SeekableStream::set_loose_mid_side_stereo(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder_, value);
-               }
-
-               bool SeekableStream::set_channels(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_channels(encoder_, value);
-               }
-
-               bool SeekableStream::set_bits_per_sample(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_bits_per_sample(encoder_, value);
-               }
-
-               bool SeekableStream::set_sample_rate(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_sample_rate(encoder_, value);
-               }
-
-               bool SeekableStream::set_blocksize(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_blocksize(encoder_, value);
-               }
-
-               bool SeekableStream::set_apodization(const char *specification)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_apodization(encoder_, specification);
-               }
-
-               bool SeekableStream::set_max_lpc_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_max_lpc_order(encoder_, value);
-               }
-
-               bool SeekableStream::set_qlp_coeff_precision(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder_, value);
-               }
-
-               bool SeekableStream::set_do_qlp_coeff_prec_search(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder_, value);
-               }
-
-               bool SeekableStream::set_do_escape_coding(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_do_escape_coding(encoder_, value);
-               }
-
-               bool SeekableStream::set_do_exhaustive_model_search(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder_, value);
-               }
-
-               bool SeekableStream::set_min_residual_partition_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder_, value);
-               }
-
-               bool SeekableStream::set_max_residual_partition_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder_, value);
-               }
-
-               bool SeekableStream::set_rice_parameter_search_dist(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder_, value);
-               }
-
-               bool SeekableStream::set_total_samples_estimate(FLAC__uint64 value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_total_samples_estimate(encoder_, value);
-               }
-
-               bool SeekableStream::set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_set_metadata(encoder_, metadata, num_blocks);
-               }
-
-               bool SeekableStream::set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks)
-               {
-                       FLAC__ASSERT(is_valid());
-#if (defined _MSC_VER) || (defined __SUNPRO_CC)
-                       // MSVC++ can't handle:
-                       // ::FLAC__StreamMetadata *m[num_blocks];
-                       // so we do this ugly workaround
-                       ::FLAC__StreamMetadata **m = new ::FLAC__StreamMetadata*[num_blocks];
-#else
-                       ::FLAC__StreamMetadata *m[num_blocks];
-#endif
-                       for(unsigned i = 0; i < num_blocks; i++) {
-                               // we can get away with this since we know the encoder will only correct the is_last flags
-                               m[i] = const_cast< ::FLAC__StreamMetadata*>((::FLAC__StreamMetadata*)metadata[i]);
-                       }
-#if (defined _MSC_VER) || (defined __SUNPRO_CC)
-                       // complete the hack
-                       const bool ok = (bool)::FLAC__seekable_stream_encoder_set_metadata(encoder_, m, num_blocks);
-                       delete [] m;
-                       return ok;
-#else
-                       return (bool)::FLAC__seekable_stream_encoder_set_metadata(encoder_, m, num_blocks);
-#endif
-               }
-
-               SeekableStream::State SeekableStream::get_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return State(::FLAC__seekable_stream_encoder_get_state(encoder_));
-               }
-
-               Stream::State SeekableStream::get_stream_encoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return Stream::State(::FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder_));
-               }
-
-               Decoder::Stream::State SeekableStream::get_verify_decoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return Decoder::Stream::State(::FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder_));
-               }
-
-               void SeekableStream::get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::FLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder_, absolute_sample, frame_number, channel, sample, expected, got);
-               }
-
-               bool SeekableStream::get_verify() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_get_verify(encoder_);
-               }
-
-               bool SeekableStream::get_streamable_subset() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_get_streamable_subset(encoder_);
-               }
-
-               bool SeekableStream::get_do_mid_side_stereo() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder_);
-               }
-
-               bool SeekableStream::get_loose_mid_side_stereo() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder_);
-               }
-
-               unsigned SeekableStream::get_channels() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_channels(encoder_);
-               }
-
-               unsigned SeekableStream::get_bits_per_sample() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_bits_per_sample(encoder_);
-               }
-
-               unsigned SeekableStream::get_sample_rate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_sample_rate(encoder_);
-               }
-
-               unsigned SeekableStream::get_blocksize() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_blocksize(encoder_);
-               }
-
-               unsigned SeekableStream::get_max_lpc_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_max_lpc_order(encoder_);
-               }
-
-               unsigned SeekableStream::get_qlp_coeff_precision() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder_);
-               }
-
-               bool SeekableStream::get_do_qlp_coeff_prec_search() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder_);
-               }
-
-               bool SeekableStream::get_do_escape_coding() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_get_do_escape_coding(encoder_);
-               }
-
-               bool SeekableStream::get_do_exhaustive_model_search() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder_);
-               }
-
-               unsigned SeekableStream::get_min_residual_partition_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder_);
-               }
-
-               unsigned SeekableStream::get_max_residual_partition_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder_);
-               }
-
-               unsigned SeekableStream::get_rice_parameter_search_dist() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder_);
-               }
-
-               FLAC__uint64 SeekableStream::get_total_samples_estimate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder_);
-               }
-
-               SeekableStream::State SeekableStream::init()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::FLAC__seekable_stream_encoder_set_seek_callback(encoder_, seek_callback_);
-                       ::FLAC__seekable_stream_encoder_set_tell_callback(encoder_, tell_callback_);
-                       ::FLAC__seekable_stream_encoder_set_write_callback(encoder_, write_callback_);
-                       ::FLAC__seekable_stream_encoder_set_client_data(encoder_, (void*)this);
-                       return State(::FLAC__seekable_stream_encoder_init(encoder_));
-               }
-
-               void SeekableStream::finish()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::FLAC__seekable_stream_encoder_finish(encoder_);
-               }
-
-               bool SeekableStream::process(const FLAC__int32 * const buffer[], unsigned samples)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_process(encoder_, buffer, samples);
-               }
-
-               bool SeekableStream::process_interleaved(const FLAC__int32 buffer[], unsigned samples)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::FLAC__seekable_stream_encoder_process_interleaved(encoder_, buffer, samples);
-               }
-
-               ::FLAC__SeekableStreamEncoderSeekStatus SeekableStream::seek_callback_(const ::FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-               {
-                       (void)encoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->seek_callback(absolute_byte_offset);
-               }
-
-               ::FLAC__SeekableStreamEncoderTellStatus SeekableStream::tell_callback_(const ::FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-               {
-                       (void)encoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->tell_callback(absolute_byte_offset);
-               }
-
-               ::FLAC__StreamEncoderWriteStatus SeekableStream::write_callback_(const ::FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-               {
-                       (void)encoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->write_callback(buffer, bytes, samples, current_frame);
-               }
-
-       }
-}
index 39cea81..79ca49a 100644 (file)
@@ -57,6 +57,12 @@ namespace FLAC {
                        return 0 != decoder_;
                }
 
+               bool Stream::set_md5_checking(bool value)
+               {
+                       FLAC__ASSERT(is_valid());
+                       return (bool)::FLAC__stream_decoder_set_md5_checking(decoder_, value);
+               }
+
                bool Stream::set_metadata_respond(::FLAC__MetadataType type)
                {
                        FLAC__ASSERT(is_valid());
@@ -99,6 +105,18 @@ namespace FLAC {
                        return State(::FLAC__stream_decoder_get_state(decoder_));
                }
 
+               bool Stream::get_md5_checking() const
+               {
+                       FLAC__ASSERT(is_valid());
+                       return (bool)::FLAC__stream_decoder_get_md5_checking(decoder_);
+               }
+
+               FLAC__uint64 Stream::get_total_samples() const
+               {
+                       FLAC__ASSERT(is_valid());
+                       return ::FLAC__stream_decoder_get_total_samples(decoder_);
+               }
+
                unsigned Stream::get_channels() const
                {
                        FLAC__ASSERT(is_valid());
@@ -129,15 +147,10 @@ namespace FLAC {
                        return ::FLAC__stream_decoder_get_blocksize(decoder_);
                }
 
-               Stream::State Stream::init()
+               ::FLAC__StreamDecoderInitStatus Stream::init()
                {
                        FLAC__ASSERT(is_valid());
-                       ::FLAC__stream_decoder_set_read_callback(decoder_, read_callback_);
-                       ::FLAC__stream_decoder_set_write_callback(decoder_, write_callback_);
-                       ::FLAC__stream_decoder_set_metadata_callback(decoder_, metadata_callback_);
-                       ::FLAC__stream_decoder_set_error_callback(decoder_, error_callback_);
-                       ::FLAC__stream_decoder_set_client_data(decoder_, (void*)this);
-                       return State(::FLAC__stream_decoder_init(decoder_));
+                       return ::FLAC__stream_decoder_init_stream(decoder_, read_callback_, seek_callback_, tell_callback_, length_callback_, eof_callback_, write_callback_, metadata_callback_, error_callback_, /*client_data=*/(void*)this);
                }
 
                void Stream::finish()
@@ -182,6 +195,40 @@ namespace FLAC {
                        return (bool)::FLAC__stream_decoder_skip_single_frame(decoder_);
                }
 
+               bool Stream::seek_absolute(FLAC__uint64 sample)
+               {
+                       FLAC__ASSERT(is_valid());
+                       return (bool)::FLAC__stream_decoder_seek_absolute(decoder_, sample);
+               }
+
+               ::FLAC__StreamDecoderSeekStatus Stream::seek_callback(FLAC__uint64 absolute_byte_offset)
+               {
+                       (void)absolute_byte_offset;
+                       return ::FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+               }
+
+               ::FLAC__StreamDecoderTellStatus Stream::tell_callback(FLAC__uint64 *absolute_byte_offset)
+               {
+                       (void)absolute_byte_offset;
+                       return ::FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
+               }
+
+               ::FLAC__StreamDecoderLengthStatus Stream::length_callback(FLAC__uint64 *stream_length)
+               {
+                       (void)stream_length;
+                       return ::FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+               }
+
+               bool Stream::eof_callback()
+               {
+                       return false;
+               }
+
+               void Stream::metadata_callback(const ::FLAC__StreamMetadata *metadata)
+               {
+                       (void)metadata;
+               }
+
                ::FLAC__StreamDecoderReadStatus Stream::read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
                {
                        (void)decoder;
@@ -191,6 +238,42 @@ namespace FLAC {
                        return instance->read_callback(buffer, bytes);
                }
 
+               ::FLAC__StreamDecoderSeekStatus Stream::seek_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+               {
+                       (void) decoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->seek_callback(absolute_byte_offset);
+               }
+
+               ::FLAC__StreamDecoderTellStatus Stream::tell_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+               {
+                       (void) decoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->tell_callback(absolute_byte_offset);
+               }
+
+               ::FLAC__StreamDecoderLengthStatus Stream::length_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
+               {
+                       (void) decoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->length_callback(stream_length);
+               }
+
+               FLAC__bool Stream::eof_callback_(const ::FLAC__StreamDecoder *decoder, void *client_data)
+               {
+                       (void) decoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->eof_callback();
+               }
+
                ::FLAC__StreamDecoderWriteStatus Stream::write_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
                {
                        (void)decoder;
index 50efce7..34a9f68 100644 (file)
@@ -184,8 +184,8 @@ namespace FLAC {
                        ::FLAC__StreamMetadata *m[num_blocks];
 #endif
                        for(unsigned i = 0; i < num_blocks; i++) {
-                               // we can get away with this since we know the encoder will only correct the is_last flags
-                               m[i] = const_cast< ::FLAC__StreamMetadata*>((::FLAC__StreamMetadata*)metadata[i]);
+                               // we can get away with the const_cast since we know the encoder will only correct the is_last flags
+                               m[i] = const_cast< ::FLAC__StreamMetadata*>((const ::FLAC__StreamMetadata*)metadata[i]);
                        }
 #if (defined _MSC_VER) || (defined __SUNPRO_CC)
                        // complete the hack
@@ -317,13 +317,10 @@ namespace FLAC {
                        return ::FLAC__stream_encoder_get_total_samples_estimate(encoder_);
                }
 
-               Stream::State Stream::init()
+               ::FLAC__StreamEncoderInitStatus Stream::init()
                {
                        FLAC__ASSERT(is_valid());
-                       ::FLAC__stream_encoder_set_write_callback(encoder_, write_callback_);
-                       ::FLAC__stream_encoder_set_metadata_callback(encoder_, metadata_callback_);
-                       ::FLAC__stream_encoder_set_client_data(encoder_, (void*)this);
-                       return State(::FLAC__stream_encoder_init(encoder_));
+                       return ::FLAC__stream_encoder_init_stream(encoder_, write_callback_, seek_callback_, tell_callback_, metadata_callback_, /*client_data=*/(void*)this);
                }
 
                void Stream::finish()
@@ -344,6 +341,23 @@ namespace FLAC {
                        return (bool)::FLAC__stream_encoder_process_interleaved(encoder_, buffer, samples);
                }
 
+               ::FLAC__StreamEncoderSeekStatus Stream::seek_callback(FLAC__uint64 absolute_byte_offset)
+               {
+                       (void)absolute_byte_offset;
+                       return ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
+               }
+
+               ::FLAC__StreamEncoderTellStatus Stream::tell_callback(FLAC__uint64 *absolute_byte_offset)
+               {
+                       (void)absolute_byte_offset;
+                       return ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
+               }
+
+               void Stream::metadata_callback(const ::FLAC__StreamMetadata *metadata)
+               {
+                       (void)metadata;
+               }
+
                ::FLAC__StreamEncoderWriteStatus Stream::write_callback_(const ::FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
                {
                        (void)encoder;
@@ -353,6 +367,24 @@ namespace FLAC {
                        return instance->write_callback(buffer, bytes, samples, current_frame);
                }
 
+               ::FLAC__StreamEncoderSeekStatus Stream::seek_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+               {
+                       (void)encoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->seek_callback(absolute_byte_offset);
+               }
+
+               ::FLAC__StreamEncoderTellStatus Stream::tell_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+               {
+                       (void)encoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->tell_callback(absolute_byte_offset);
+               }
+
                void Stream::metadata_callback_(const ::FLAC__StreamEncoder *encoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
                {
                        (void)encoder;
index 395308f..efe290b 100644 (file)
@@ -87,8 +87,6 @@ libFLAC_la_SOURCES = \
        bitmath.c \
        cpu.c \
        crc.c \
-       file_decoder.c \
-       file_encoder.c \
        fixed.c \
        float.c \
        format.c \
@@ -97,8 +95,6 @@ libFLAC_la_SOURCES = \
        memory.c \
        metadata_iterators.c \
        metadata_object.c \
-       seekable_stream_decoder.c \
-       seekable_stream_encoder.c \
        stream_decoder.c \
        stream_encoder.c \
        stream_encoder_framing.c \
index 4bd906d..aac6f11 100644 (file)
@@ -65,8 +65,6 @@ SRCS_C = \
        bitmath.c \
        cpu.c \
        crc.c \
-       file_decoder.c \
-       file_encoder.c \
        fixed.c \
        float.c \
        format.c \
@@ -75,8 +73,6 @@ SRCS_C = \
        memory.c \
        metadata_iterators.c \
        metadata_object.c \
-       seekable_stream_decoder.c \
-       seekable_stream_encoder.c \
        stream_decoder.c \
        stream_encoder.c \
        stream_encoder_framing.c \
diff --git a/src/libFLAC/file_decoder.c b/src/libFLAC/file_decoder.c
deleted file mode 100644 (file)
index 6e499ed..0000000
+++ /dev/null
@@ -1,681 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for strcmp() */
-#include <sys/stat.h> /* for stat() */
-#if defined _MSC_VER || defined __MINGW32__
-#include <io.h> /* for _setmode() */
-#include <fcntl.h> /* for _O_BINARY */
-#include <sys/types.h> /* for off_t */
-//@@@ [2G limit] hacks for MSVC6
-#define fseeko fseek
-#define ftello ftell
-#elif defined __CYGWIN__
-#include <io.h> /* for setmode(), O_BINARY */
-#include <fcntl.h> /* for _O_BINARY */
-#endif
-#include "FLAC/assert.h"
-#include "protected/file_decoder.h"
-#include "protected/seekable_stream_decoder.h"
-
-/***********************************************************************
- *
- * Private class method prototypes
- *
- ***********************************************************************/
-
-static void set_defaults_(FLAC__FileDecoder *decoder);
-static FILE *get_binary_stdin_();
-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);
-
-/***********************************************************************
- *
- * Private class data
- *
- ***********************************************************************/
-
-typedef struct FLAC__FileDecoderPrivate {
-       FLAC__FileDecoderWriteCallback write_callback;
-       FLAC__FileDecoderMetadataCallback metadata_callback;
-       FLAC__FileDecoderErrorCallback error_callback;
-       void *client_data;
-       FILE *file;
-       char *filename; /* == NULL if stdin */
-       FLAC__SeekableStreamDecoder *seekable_stream_decoder;
-} FLAC__FileDecoderPrivate;
-
-/***********************************************************************
- *
- * Public static class data
- *
- ***********************************************************************/
-
-FLAC_API const char * const FLAC__FileDecoderStateString[] = {
-       "FLAC__FILE_DECODER_OK",
-       "FLAC__FILE_DECODER_END_OF_FILE",
-       "FLAC__FILE_DECODER_ERROR_OPENING_FILE",
-       "FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR",
-       "FLAC__FILE_DECODER_SEEK_ERROR",
-       "FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR",
-       "FLAC__FILE_DECODER_ALREADY_INITIALIZED",
-       "FLAC__FILE_DECODER_INVALID_CALLBACK",
-       "FLAC__FILE_DECODER_UNINITIALIZED"
-};
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-FLAC_API FLAC__FileDecoder *FLAC__file_decoder_new()
-{
-       FLAC__FileDecoder *decoder;
-
-       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
-
-       decoder = (FLAC__FileDecoder*)calloc(1, sizeof(FLAC__FileDecoder));
-       if(decoder == 0) {
-               return 0;
-       }
-
-       decoder->protected_ = (FLAC__FileDecoderProtected*)calloc(1, sizeof(FLAC__FileDecoderProtected));
-       if(decoder->protected_ == 0) {
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_ = (FLAC__FileDecoderPrivate*)calloc(1, sizeof(FLAC__FileDecoderPrivate));
-       if(decoder->private_ == 0) {
-               free(decoder->protected_);
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_->seekable_stream_decoder = FLAC__seekable_stream_decoder_new();
-       if(0 == decoder->private_->seekable_stream_decoder) {
-               free(decoder->private_);
-               free(decoder->protected_);
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_->file = 0;
-
-       set_defaults_(decoder);
-
-       decoder->protected_->state = FLAC__FILE_DECODER_UNINITIALIZED;
-
-       return decoder;
-}
-
-FLAC_API void FLAC__file_decoder_delete(FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-
-       (void)FLAC__file_decoder_finish(decoder);
-
-       FLAC__seekable_stream_decoder_delete(decoder->private_->seekable_stream_decoder);
-
-       free(decoder->private_);
-       free(decoder->protected_);
-       free(decoder);
-}
-
-/***********************************************************************
- *
- * Public class methods
- *
- ***********************************************************************/
-
-FLAC_API FLAC__FileDecoderState FLAC__file_decoder_init(FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return decoder->protected_->state = FLAC__FILE_DECODER_ALREADY_INITIALIZED;
-
-       if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
-               return decoder->protected_->state = FLAC__FILE_DECODER_INVALID_CALLBACK;
-
-       if(0 == decoder->private_->filename)
-               decoder->private_->file = get_binary_stdin_();
-       else
-               decoder->private_->file = fopen(decoder->private_->filename, "rb");
-
-       if(decoder->private_->file == 0)
-               return decoder->protected_->state = FLAC__FILE_DECODER_ERROR_OPENING_FILE;
-
-       FLAC__seekable_stream_decoder_set_read_callback(decoder->private_->seekable_stream_decoder, read_callback_);
-       FLAC__seekable_stream_decoder_set_seek_callback(decoder->private_->seekable_stream_decoder, seek_callback_);
-       FLAC__seekable_stream_decoder_set_tell_callback(decoder->private_->seekable_stream_decoder, tell_callback_);
-       FLAC__seekable_stream_decoder_set_length_callback(decoder->private_->seekable_stream_decoder, length_callback_);
-       FLAC__seekable_stream_decoder_set_eof_callback(decoder->private_->seekable_stream_decoder, eof_callback_);
-       FLAC__seekable_stream_decoder_set_write_callback(decoder->private_->seekable_stream_decoder, write_callback_);
-       FLAC__seekable_stream_decoder_set_metadata_callback(decoder->private_->seekable_stream_decoder, metadata_callback_);
-       FLAC__seekable_stream_decoder_set_error_callback(decoder->private_->seekable_stream_decoder, error_callback_);
-       FLAC__seekable_stream_decoder_set_client_data(decoder->private_->seekable_stream_decoder, decoder);
-
-       if(FLAC__seekable_stream_decoder_init(decoder->private_->seekable_stream_decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK)
-               return decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return decoder->protected_->state = FLAC__FILE_DECODER_OK;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_finish(FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->protected_->state == FLAC__FILE_DECODER_UNINITIALIZED)
-               return true;
-
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-
-       if(0 != decoder->private_->file && decoder->private_->file != stdin) {
-               fclose(decoder->private_->file);
-               decoder->private_->file = 0;
-       }
-
-       if(0 != decoder->private_->filename) {
-               free(decoder->private_->filename);
-               decoder->private_->filename = 0;
-       }
-
-       set_defaults_(decoder);
-
-       decoder->protected_->state = FLAC__FILE_DECODER_UNINITIALIZED;
-
-       return FLAC__seekable_stream_decoder_finish(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_md5_checking(FLAC__FileDecoder *decoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_decoder_set_md5_checking(decoder->private_->seekable_stream_decoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_filename(FLAC__FileDecoder *decoder, const char *value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       if(0 != decoder->private_->filename) {
-               free(decoder->private_->filename);
-               decoder->private_->filename = 0;
-       }
-       if(0 != strcmp(value, "-")) {
-               if(0 == (decoder->private_->filename = (char*)malloc(strlen(value)+1))) {
-                       decoder->protected_->state = FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR;
-                       return false;
-               }
-               strcpy(decoder->private_->filename, value);
-       }
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_write_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->write_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderMetadataCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->metadata_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_error_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderErrorCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->error_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_client_data(FLAC__FileDecoder *decoder, void *value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->client_data = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond(FLAC__FileDecoder *decoder, FLAC__MetadataType type)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_decoder_set_metadata_respond(decoder->private_->seekable_stream_decoder, type);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond_application(FLAC__FileDecoder *decoder, const FLAC__byte id[4])
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder->private_->seekable_stream_decoder, id);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond_all(FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore(FLAC__FileDecoder *decoder, FLAC__MetadataType type)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_decoder_set_metadata_ignore(decoder->private_->seekable_stream_decoder, type);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore_application(FLAC__FileDecoder *decoder, const FLAC__byte id[4])
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder->private_->seekable_stream_decoder, id);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore_all(FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API FLAC__FileDecoderState FLAC__file_decoder_get_state(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       return decoder->protected_->state;
-}
-
-FLAC_API FLAC__SeekableStreamDecoderState FLAC__file_decoder_get_seekable_stream_decoder_state(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_state(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API FLAC__StreamDecoderState FLAC__file_decoder_get_stream_decoder_state(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_stream_decoder_state(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API const char *FLAC__file_decoder_get_resolved_state_string(const FLAC__FileDecoder *decoder)
-{
-       if(decoder->protected_->state != FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR)
-               return FLAC__FileDecoderStateString[decoder->protected_->state];
-       else
-               return FLAC__seekable_stream_decoder_get_resolved_state_string(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_get_md5_checking(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_md5_checking(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API unsigned FLAC__file_decoder_get_channels(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_channels(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API FLAC__ChannelAssignment FLAC__file_decoder_get_channel_assignment(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_channel_assignment(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API unsigned FLAC__file_decoder_get_bits_per_sample(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_bits_per_sample(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API unsigned FLAC__file_decoder_get_sample_rate(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_sample_rate(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API unsigned FLAC__file_decoder_get_blocksize(const FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_blocksize(decoder->private_->seekable_stream_decoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_get_decode_position(const FLAC__FileDecoder *decoder, FLAC__uint64 *position)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__seekable_stream_decoder_get_decode_position(decoder->private_->seekable_stream_decoder, position);
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_process_single(FLAC__FileDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
-
-       if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
-
-       ret = FLAC__seekable_stream_decoder_process_single(decoder->private_->seekable_stream_decoder);
-       if(!ret)
-               decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_metadata(FLAC__FileDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
-
-       if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
-
-       ret = FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder->private_->seekable_stream_decoder);
-       if(!ret)
-               decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_file(FLAC__FileDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
-
-       if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
-
-       ret = FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder->private_->seekable_stream_decoder);
-       if(!ret)
-               decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_skip_single_frame(FLAC__FileDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
-
-       if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
-
-       ret = FLAC__seekable_stream_decoder_skip_single_frame(decoder->private_->seekable_stream_decoder);
-       if(!ret)
-               decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-FLAC_API FLAC__bool FLAC__file_decoder_seek_absolute(FLAC__FileDecoder *decoder, FLAC__uint64 sample)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK || decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE);
-
-       if(decoder->private_->filename == 0) { /* means the file is stdin... */
-               decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
-               return false;
-       }
-
-       if(!FLAC__seekable_stream_decoder_seek_absolute(decoder->private_->seekable_stream_decoder, sample)) {
-               decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
-               return false;
-       }
-       else {
-               decoder->protected_->state = FLAC__FILE_DECODER_OK;
-               return true;
-       }
-}
-
-
-/***********************************************************************
- *
- * Private class methods
- *
- ***********************************************************************/
-
-void set_defaults_(FLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-
-       decoder->private_->filename = 0;
-       decoder->private_->write_callback = 0;
-       decoder->private_->metadata_callback = 0;
-       decoder->private_->error_callback = 0;
-       decoder->private_->client_data = 0;
-}
-
-/*
- * This will forcibly set stdin to binary mode (for OSes that require it)
- */
-FILE *get_binary_stdin_()
-{
-       /* if something breaks here it is probably due to the presence or
-        * absence of an underscore before the identifiers 'setmode',
-        * 'fileno', and/or 'O_BINARY'; check your system header files.
-        */
-#if defined _MSC_VER || defined __MINGW32__
-       _setmode(_fileno(stdin), _O_BINARY);
-#elif defined __CYGWIN__
-       /* almost certainly not needed for any modern Cygwin, but let's be safe... */
-       setmode(_fileno(stdin), _O_BINARY);
-#endif
-
-       return stdin;
-}
-
-FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-{
-       FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       if(*bytes > 0) {
-               *bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, file_decoder->private_->file);
-               if(ferror(file_decoder->private_->file)) {
-                       return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-               }
-               else {
-                       return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-               }
-       }
-       else
-               return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
-}
-
-FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-{
-       FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       if(fseeko(file_decoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
-               return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-       else
-               return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-{
-       FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
-       off_t pos;
-       (void)decoder;
-
-       if((pos = ftello(file_decoder->private_->file)) < 0)
-               return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-       else {
-               *absolute_byte_offset = (FLAC__uint64)pos;
-               return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
-       }
-}
-
-FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
-{
-       FLAC__FileDecoder *file_decoder = (FLAC__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;
-       else {
-               *stream_length = (FLAC__uint64)filestats.st_size;
-               return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
-       }
-}
-
-FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data)
-{
-       FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       return feof(file_decoder->private_->file)? true : false;
-}
-
-FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       return file_decoder->private_->write_callback(file_decoder, frame, buffer, file_decoder->private_->client_data);
-}
-
-void metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       file_decoder->private_->metadata_callback(file_decoder, metadata, file_decoder->private_->client_data);
-}
-
-void error_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       file_decoder->private_->error_callback(file_decoder, status, file_decoder->private_->client_data);
-}
diff --git a/src/libFLAC/file_encoder.c b/src/libFLAC/file_encoder.c
deleted file mode 100644 (file)
index 3469bfd..0000000
+++ /dev/null
@@ -1,797 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for strlen(), strcpy() */
-#if defined _MSC_VER || defined __MINGW32__
-#include <sys/types.h> /* for off_t */
-//@@@ [2G limit] hacks for MSVC6
-#define fseeko fseek
-#define ftello ftell
-#endif
-#include "FLAC/assert.h"
-#include "protected/file_encoder.h"
-
-#ifdef max
-#undef max
-#endif
-#define max(x,y) ((x)>(y)?(x):(y))
-
-/***********************************************************************
- *
- * Private class method prototypes
- *
- ***********************************************************************/
-
-/* unpublished debug routines */
-extern FLAC__bool FLAC__seekable_stream_encoder_disable_constant_subframes(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__seekable_stream_encoder_disable_fixed_subframes(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__seekable_stream_encoder_disable_verbatim_subframes(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-static void set_defaults_(FLAC__FileEncoder *encoder);
-static FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-static FLAC__SeekableStreamEncoderTellStatus tell_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-
-/***********************************************************************
- *
- * Private class data
- *
- ***********************************************************************/
-
-typedef struct FLAC__FileEncoderPrivate {
-       FLAC__FileEncoderProgressCallback progress_callback;
-       void *client_data;
-       char *filename;
-       FLAC__uint64 bytes_written;
-       FLAC__uint64 samples_written;
-       unsigned frames_written;
-       unsigned total_frames_estimate;
-       FLAC__SeekableStreamEncoder *seekable_stream_encoder;
-       FILE *file;
-} FLAC__FileEncoderPrivate;
-
-/***********************************************************************
- *
- * Public static class data
- *
- ***********************************************************************/
-
-FLAC_API const char * const FLAC__FileEncoderStateString[] = {
-       "FLAC__FILE_ENCODER_OK",
-       "FLAC__FILE_ENCODER_NO_FILENAME",
-       "FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR",
-       "FLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING",
-       "FLAC__FILE_ENCODER_ERROR_OPENING_FILE",
-       "FLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR",
-       "FLAC__FILE_ENCODER_ALREADY_INITIALIZED",
-       "FLAC__FILE_ENCODER_UNINITIALIZED"
-};
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-FLAC_API FLAC__FileEncoder *FLAC__file_encoder_new()
-{
-       FLAC__FileEncoder *encoder;
-
-       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
-
-       encoder = (FLAC__FileEncoder*)calloc(1, sizeof(FLAC__FileEncoder));
-       if(encoder == 0) {
-               return 0;
-       }
-
-       encoder->protected_ = (FLAC__FileEncoderProtected*)calloc(1, sizeof(FLAC__FileEncoderProtected));
-       if(encoder->protected_ == 0) {
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_ = (FLAC__FileEncoderPrivate*)calloc(1, sizeof(FLAC__FileEncoderPrivate));
-       if(encoder->private_ == 0) {
-               free(encoder->protected_);
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_->seekable_stream_encoder = FLAC__seekable_stream_encoder_new();
-       if(0 == encoder->private_->seekable_stream_encoder) {
-               free(encoder->private_);
-               free(encoder->protected_);
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_->file = 0;
-
-       set_defaults_(encoder);
-
-       encoder->protected_->state = FLAC__FILE_ENCODER_UNINITIALIZED;
-
-       return encoder;
-}
-
-FLAC_API void FLAC__file_encoder_delete(FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-
-       (void)FLAC__file_encoder_finish(encoder);
-
-       FLAC__seekable_stream_encoder_delete(encoder->private_->seekable_stream_encoder);
-
-       free(encoder->private_);
-       free(encoder->protected_);
-       free(encoder);
-}
-
-/***********************************************************************
- *
- * Public class methods
- *
- ***********************************************************************/
-
-FLAC_API FLAC__FileEncoderState FLAC__file_encoder_init(FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return encoder->protected_->state = FLAC__FILE_ENCODER_ALREADY_INITIALIZED;
-
-       if(0 == encoder->private_->filename)
-               return encoder->protected_->state = FLAC__FILE_ENCODER_NO_FILENAME;
-
-       encoder->private_->file = fopen(encoder->private_->filename, "w+b");
-
-       if(encoder->private_->file == 0)
-               return encoder->protected_->state = FLAC__FILE_ENCODER_ERROR_OPENING_FILE;
-
-       encoder->private_->bytes_written = 0;
-       encoder->private_->samples_written = 0;
-       encoder->private_->frames_written = 0;
-
-       FLAC__seekable_stream_encoder_set_seek_callback(encoder->private_->seekable_stream_encoder, seek_callback_);
-       FLAC__seekable_stream_encoder_set_tell_callback(encoder->private_->seekable_stream_encoder, tell_callback_);
-       FLAC__seekable_stream_encoder_set_write_callback(encoder->private_->seekable_stream_encoder, write_callback_);
-       FLAC__seekable_stream_encoder_set_client_data(encoder->private_->seekable_stream_encoder, encoder);
-
-       if(FLAC__seekable_stream_encoder_init(encoder->private_->seekable_stream_encoder) != FLAC__SEEKABLE_STREAM_ENCODER_OK)
-               return encoder->protected_->state = FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
-
-       {
-               unsigned blocksize = FLAC__file_encoder_get_blocksize(encoder);
-
-               FLAC__ASSERT(blocksize != 0);
-               encoder->private_->total_frames_estimate = (unsigned)((FLAC__file_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize);
-       }
-
-       return encoder->protected_->state = FLAC__FILE_ENCODER_OK;
-}
-
-FLAC_API void FLAC__file_encoder_finish(FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-
-       if(encoder->protected_->state == FLAC__FILE_ENCODER_UNINITIALIZED)
-               return;
-
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-
-       /* FLAC__seekable_stream_encoder_finish() might write data so we must close the file after it. */
-
-       FLAC__seekable_stream_encoder_finish(encoder->private_->seekable_stream_encoder);
-
-       if(0 != encoder->private_->file) {
-               fclose(encoder->private_->file);
-               encoder->private_->file = 0;
-       }
-
-       if(0 != encoder->private_->filename) {
-               free(encoder->private_->filename);
-               encoder->private_->filename = 0;
-       }
-
-       set_defaults_(encoder);
-
-       encoder->protected_->state = FLAC__FILE_ENCODER_UNINITIALIZED;
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_verify(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_verify(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_streamable_subset(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_streamable_subset(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_do_mid_side_stereo(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_loose_mid_side_stereo(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_channels(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_channels(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_bits_per_sample(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_bits_per_sample(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_sample_rate(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_sample_rate(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_blocksize(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_blocksize(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_apodization(FLAC__FileEncoder *encoder, const char *specification)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_apodization(encoder->private_->seekable_stream_encoder, specification);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_max_lpc_order(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_max_lpc_order(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_qlp_coeff_precision(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_do_qlp_coeff_prec_search(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_do_escape_coding(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_do_escape_coding(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_do_exhaustive_model_search(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_min_residual_partition_order(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_max_residual_partition_order(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_rice_parameter_search_dist(FLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_total_samples_estimate(FLAC__FileEncoder *encoder, FLAC__uint64 value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_total_samples_estimate(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_metadata(FLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_set_metadata(encoder->private_->seekable_stream_encoder, metadata, num_blocks);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_filename(FLAC__FileEncoder *encoder, const char *value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       if(0 != encoder->private_->filename) {
-               free(encoder->private_->filename);
-               encoder->private_->filename = 0;
-       }
-       if(0 == (encoder->private_->filename = (char*)malloc(strlen(value)+1))) {
-               encoder->protected_->state = FLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR;
-               return false;
-       }
-       strcpy(encoder->private_->filename, value);
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_progress_callback(FLAC__FileEncoder *encoder, FLAC__FileEncoderProgressCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->progress_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_set_client_data(FLAC__FileEncoder *encoder, void *value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->client_data = value;
-       return true;
-}
-
-/*
- * These three functions are not static, but not publically exposed in
- * include/FLAC/ either.  They are used by the test suite.
- */
-FLAC_API FLAC__bool FLAC__file_encoder_disable_constant_subframes(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_disable_constant_subframes(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_disable_fixed_subframes(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_disable_fixed_subframes(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_disable_verbatim_subframes(FLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__seekable_stream_encoder_disable_verbatim_subframes(encoder->private_->seekable_stream_encoder, value);
-}
-
-FLAC_API FLAC__FileEncoderState FLAC__file_encoder_get_state(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->protected_);
-       return encoder->protected_->state;
-}
-
-FLAC_API FLAC__SeekableStreamEncoderState FLAC__file_encoder_get_seekable_stream_encoder_state(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_state(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__StreamEncoderState FLAC__file_encoder_get_stream_encoder_state(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__StreamDecoderState FLAC__file_encoder_get_verify_decoder_state(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API const char *FLAC__file_encoder_get_resolved_state_string(const FLAC__FileEncoder *encoder)
-{
-       if(encoder->protected_->state != FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR)
-               return FLAC__FileEncoderStateString[encoder->protected_->state];
-       else
-               return FLAC__seekable_stream_encoder_get_resolved_state_string(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API void FLAC__file_encoder_get_verify_decoder_error_stats(const FLAC__FileEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder->private_->seekable_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_get_verify(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_verify(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_get_streamable_subset(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_streamable_subset(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_get_do_mid_side_stereo(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_get_loose_mid_side_stereo(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_channels(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_channels(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_bits_per_sample(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_bits_per_sample(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_sample_rate(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_sample_rate(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_blocksize(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_blocksize(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_max_lpc_order(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_max_lpc_order(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_qlp_coeff_precision(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_get_do_qlp_coeff_prec_search(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_get_do_escape_coding(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_do_escape_coding(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_get_do_exhaustive_model_search(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_min_residual_partition_order(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_max_residual_partition_order(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API unsigned FLAC__file_encoder_get_rice_parameter_search_dist(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__uint64 FLAC__file_encoder_get_total_samples_estimate(const FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->seekable_stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__file_encoder_process(FLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       if(!FLAC__seekable_stream_encoder_process(encoder->private_->seekable_stream_encoder, buffer, samples)) {
-               encoder->protected_->state = FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
-               return false;
-       }
-       else
-               return true;
-}
-
-/* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
-FLAC_API FLAC__bool FLAC__file_encoder_process_interleaved(FLAC__FileEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       if(!FLAC__seekable_stream_encoder_process_interleaved(encoder->private_->seekable_stream_encoder, buffer, samples)) {
-               encoder->protected_->state = FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
-               return false;
-       }
-       else
-               return true;
-}
-
-
-/***********************************************************************
- *
- * Private class methods
- *
- ***********************************************************************/
-
-void set_defaults_(FLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-
-       encoder->private_->progress_callback = 0;
-       encoder->private_->client_data = 0;
-       encoder->private_->total_frames_estimate = 0;
-       encoder->private_->filename = 0;
-}
-
-FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-{
-       FLAC__FileEncoder *file_encoder = (FLAC__FileEncoder*)client_data;
-
-       (void)encoder;
-
-       FLAC__ASSERT(0 != file_encoder);
-
-       if(fseeko(file_encoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
-               return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR;
-       else
-               return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
-}
-
-FLAC__SeekableStreamEncoderTellStatus tell_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-{
-       FLAC__FileEncoder *file_encoder = (FLAC__FileEncoder*)client_data;
-       off_t offset;
-
-       (void)encoder;
-
-       FLAC__ASSERT(0 != file_encoder);
-
-       offset = ftello(file_encoder->private_->file);
-
-       if(offset < 0) {
-               return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_ERROR;
-       }
-       else {
-               *absolute_byte_offset = (FLAC__uint64)offset;
-               return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK;
-       }
-}
-
-#ifdef FLAC__VALGRIND_TESTING
-static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
-       size_t ret = fwrite(ptr, size, nmemb, stream);
-       if(!ferror(stream))
-               fflush(stream);
-       return ret;
-}
-#else
-#define local__fwrite fwrite
-#endif
-
-FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       FLAC__FileEncoder *file_encoder = (FLAC__FileEncoder*)client_data;
-
-       (void)encoder, (void)samples, (void)current_frame;
-
-       FLAC__ASSERT(0 != file_encoder);
-
-       if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, file_encoder->private_->file) == bytes) {
-               file_encoder->private_->bytes_written += bytes;
-               file_encoder->private_->samples_written += samples;
-               /* we keep a high watermark on the number of frames written because
-                * when the encoder goes back to write metadata, 'current_frame'
-                * will drop back to 0.
-                */
-               file_encoder->private_->frames_written = max(file_encoder->private_->frames_written, current_frame+1);
-               if(0 != file_encoder->private_->progress_callback && samples > 0)
-                       file_encoder->private_->progress_callback(file_encoder, file_encoder->private_->bytes_written, file_encoder->private_->samples_written, file_encoder->private_->frames_written, file_encoder->private_->total_frames_estimate, file_encoder->private_->client_data);
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-       }
-       else
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
-}
index fc20d70..9c3e5df 100644 (file)
@@ -30,9 +30,5 @@
 
 noinst_HEADERS = \
        all.h \
-       file_decoder.h \
-       file_encoder.h \
-       seekable_stream_decoder.h \
-       seekable_stream_encoder.h \
        stream_decoder.h \
        stream_encoder.h
index 832f7fb..81a04c7 100644 (file)
 #ifndef FLAC__PROTECTED__ALL_H
 #define FLAC__PROTECTED__ALL_H
 
-#include "file_decoder.h"
-#include "file_encoder.h"
-#include "seekable_stream_decoder.h"
-#include "seekable_stream_encoder.h"
 #include "stream_decoder.h"
 #include "stream_encoder.h"
 
diff --git a/src/libFLAC/include/protected/file_decoder.h b/src/libFLAC/include/protected/file_decoder.h
deleted file mode 100644 (file)
index caeb556..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLAC__PROTECTED__FILE_DECODER_H
-#define FLAC__PROTECTED__FILE_DECODER_H
-
-#include "FLAC/file_decoder.h"
-
-typedef struct FLAC__FileDecoderProtected {
-       FLAC__FileDecoderState state;
-} FLAC__FileDecoderProtected;
-
-#endif
diff --git a/src/libFLAC/include/protected/file_encoder.h b/src/libFLAC/include/protected/file_encoder.h
deleted file mode 100644 (file)
index 73fc51a..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2001,2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLAC__PROTECTED__FILE_ENCODER_H
-#define FLAC__PROTECTED__FILE_ENCODER_H
-
-#include "FLAC/file_encoder.h"
-
-typedef struct FLAC__FileEncoderProtected {
-       FLAC__FileEncoderState state;
-} FLAC__FileEncoderProtected;
-
-#endif
diff --git a/src/libFLAC/include/protected/seekable_stream_decoder.h b/src/libFLAC/include/protected/seekable_stream_decoder.h
deleted file mode 100644 (file)
index c07ce28..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLAC__PROTECTED__SEEKABLE_STREAM_DECODER_H
-#define FLAC__PROTECTED__SEEKABLE_STREAM_DECODER_H
-
-#include "FLAC/seekable_stream_decoder.h"
-
-typedef struct FLAC__SeekableStreamDecoderProtected {
-       FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */
-       FLAC__SeekableStreamDecoderState state;
-} FLAC__SeekableStreamDecoderProtected;
-
-#endif
diff --git a/src/libFLAC/include/protected/seekable_stream_encoder.h b/src/libFLAC/include/protected/seekable_stream_encoder.h
deleted file mode 100644 (file)
index 9be906d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FLAC__PROTECTED__SEEKABLE_STREAM_ENCODER_H
-#define FLAC__PROTECTED__SEEKABLE_STREAM_ENCODER_H
-
-#include "FLAC/seekable_stream_encoder.h"
-
-typedef struct FLAC__SeekableStreamEncoderProtected {
-       FLAC__SeekableStreamEncoderState state;
-       FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset;
-} FLAC__SeekableStreamEncoderProtected;
-
-#endif
index 0b7391a..d4c5559 100644 (file)
@@ -41,6 +41,7 @@ typedef struct FLAC__StreamDecoderProtected {
        unsigned bits_per_sample;
        unsigned sample_rate; /* in Hz */
        unsigned blocksize; /* in samples (per channel) */
+       FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */
 } FLAC__StreamDecoderProtected;
 
 /*
index 9be03f5..5233b20 100644 (file)
@@ -97,6 +97,7 @@ typedef struct FLAC__StreamEncoderProtected {
        FLAC__uint64 total_samples_estimate;
        FLAC__StreamMetadata **metadata;
        unsigned num_metadata_blocks;
+       FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset;
 } FLAC__StreamEncoderProtected;
 
 #endif
index 96802f0..5d8df0e 100644 (file)
@@ -203,14 +203,6 @@ SOURCE=.\crc.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\file_decoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\file_encoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\fixed.c\r
 # End Source File\r
 # Begin Source File\r
@@ -243,14 +235,6 @@ SOURCE=.\metadata_object.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\seekable_stream_decoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\seekable_stream_encoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\stream_decoder.c\r
 # End Source File\r
 # Begin Source File\r
@@ -335,22 +319,6 @@ SOURCE=.\include\protected\all.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\include\protected\file_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\file_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\seekable_stream_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\seekable_stream_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\include\protected\stream_decoder.h\r
 # End Source File\r
 # Begin Source File\r
@@ -375,14 +343,6 @@ SOURCE=..\..\include\FLAC\export.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\include\FLAC\file_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\FLAC\file_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\include\FLAC\format.h\r
 # End Source File\r
 # Begin Source File\r
@@ -395,14 +355,6 @@ SOURCE=..\..\include\FLAC\ordinals.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\include\FLAC\seekable_stream_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\FLAC\seekable_stream_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\include\FLAC\stream_decoder.h\r
 # End Source File\r
 # Begin Source File\r
index 53b954a..df72d27 100644 (file)
@@ -196,14 +196,6 @@ SOURCE=.\crc.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\file_decoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\file_encoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\fixed.c\r
 # End Source File\r
 # Begin Source File\r
@@ -236,14 +228,6 @@ SOURCE=.\metadata_object.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\seekable_stream_decoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\seekable_stream_encoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\stream_decoder.c\r
 # End Source File\r
 # Begin Source File\r
@@ -328,22 +312,6 @@ SOURCE=.\include\protected\all.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\include\protected\file_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\file_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\seekable_stream_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\seekable_stream_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\include\protected\stream_decoder.h\r
 # End Source File\r
 # Begin Source File\r
@@ -368,14 +336,6 @@ SOURCE=..\..\include\FLAC\export.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\include\FLAC\file_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\FLAC\file_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\include\FLAC\format.h\r
 # End Source File\r
 # Begin Source File\r
@@ -388,14 +348,6 @@ SOURCE=..\..\include\FLAC\ordinals.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\include\FLAC\seekable_stream_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\FLAC\seekable_stream_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\include\FLAC\stream_decoder.h\r
 # End Source File\r
 # Begin Source File\r
index 525b759..b023c74 100644 (file)
@@ -55,7 +55,7 @@
 #include "private/metadata.h"
 
 #include "FLAC/assert.h"
-#include "FLAC/file_decoder.h"
+#include "FLAC/stream_decoder.h"
 
 #ifdef max
 #undef max
@@ -155,9 +155,9 @@ static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *st
  *
  ***************************************************************************/
 
-static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
 
 typedef struct {
        FLAC__bool got_error;
@@ -167,43 +167,38 @@ typedef struct {
 static FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type)
 {
        level0_client_data cd;
-       FLAC__FileDecoder *decoder;
+       FLAC__StreamDecoder *decoder;
 
        FLAC__ASSERT(0 != filename);
 
        cd.got_error = false;
        cd.object = 0;
 
-       decoder = FLAC__file_decoder_new();
+       decoder = FLAC__stream_decoder_new();
 
        if(0 == decoder)
                return 0;
 
-       FLAC__file_decoder_set_md5_checking(decoder, false);
-       FLAC__file_decoder_set_filename(decoder, filename);
-       FLAC__file_decoder_set_metadata_ignore_all(decoder);
-       FLAC__file_decoder_set_metadata_respond(decoder, type);
-       FLAC__file_decoder_set_write_callback(decoder, write_callback_);
-       FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
-       FLAC__file_decoder_set_error_callback(decoder, error_callback_);
-       FLAC__file_decoder_set_client_data(decoder, &cd);
-
-       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK || cd.got_error) {
-               FLAC__file_decoder_finish(decoder);
-               FLAC__file_decoder_delete(decoder);
+       FLAC__stream_decoder_set_md5_checking(decoder, false);
+       FLAC__stream_decoder_set_metadata_ignore_all(decoder);
+       FLAC__stream_decoder_set_metadata_respond(decoder, type);
+
+       if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &cd) != FLAC__STREAM_DECODER_INIT_STATUS_OK || cd.got_error) {
+               FLAC__stream_decoder_finish(decoder);
+               FLAC__stream_decoder_delete(decoder);
                return 0;
        }
 
-       if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
-               FLAC__file_decoder_finish(decoder);
-               FLAC__file_decoder_delete(decoder);
+       if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
+               FLAC__stream_decoder_finish(decoder);
+               FLAC__stream_decoder_delete(decoder);
                if(0 != cd.object)
                        FLAC__metadata_object_delete(cd.object);
                return 0;
        }
 
-       FLAC__file_decoder_finish(decoder);
-       FLAC__file_decoder_delete(decoder);
+       FLAC__stream_decoder_finish(decoder);
+       FLAC__stream_decoder_delete(decoder);
 
        return cd.object;
 }
@@ -248,14 +243,14 @@ FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__Stre
        return 0 != *cuesheet;
 }
 
-FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
        (void)decoder, (void)frame, (void)buffer, (void)client_data;
 
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
 
-void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        level0_client_data *cd = (level0_client_data *)client_data;
        (void)decoder;
@@ -270,7 +265,7 @@ void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMeta
        }
 }
 
-void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
        level0_client_data *cd = (level0_client_data *)client_data;
        (void)decoder;
index 521a49b..6846c3b 100644 (file)
@@ -935,7 +935,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_point
        FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
        FLAC__ASSERT(total_samples > 0);
 
-       if(num > 0) {
+       if(num > 0 && total_samples > 0) {
                FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table;
                unsigned i, j;
 
@@ -954,6 +954,39 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_point
        return true;
 }
 
+FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples)
+{
+       FLAC__ASSERT(0 != object);
+       FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
+       FLAC__ASSERT(samples > 0);
+       FLAC__ASSERT(total_samples > 0);
+
+       if(samples > 0 && total_samples > 0) {
+               FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table;
+               unsigned i, j;
+               FLAC__uint64 num, sample;
+
+               num = 1 + total_samples / samples; /* 1+ for the first sample at 0 */
+               /* now account for the fact that we don't place a seekpoint at "total_samples" since samples are number from 0: */
+               if(total_samples % samples == 0)
+                       num--;
+
+               i = seek_table->num_points;
+
+               if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + num))
+                       return false;
+
+               sample = 0;
+               for(j = 0; j < num; i++, j++, sample += samples) {
+                       seek_table->points[i].sample_number = sample;
+                       seek_table->points[i].stream_offset = 0;
+                       seek_table->points[i].frame_samples = 0;
+               }
+       }
+
+       return true;
+}
+
 FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_sort(FLAC__StreamMetadata *object, FLAC__bool compact)
 {
        unsigned unique;
diff --git a/src/libFLAC/seekable_stream_decoder.c b/src/libFLAC/seekable_stream_decoder.c
deleted file mode 100644 (file)
index 0f9dc30..0000000
+++ /dev/null
@@ -1,1117 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h> /* for calloc() */
-#include <string.h> /* for memcpy()/memcmp() */
-#include "FLAC/assert.h"
-#include "protected/seekable_stream_decoder.h"
-#include "protected/stream_decoder.h"
-#include "private/float.h" /* for FLAC__double */
-#include "private/md5.h"
-
-/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
-#ifdef _MSC_VER
-#define FLAC__U64L(x) x
-#else
-#define FLAC__U64L(x) x##LLU
-#endif
-
-/***********************************************************************
- *
- * Private class method prototypes
- *
- ***********************************************************************/
-
-static void set_defaults_(FLAC__SeekableStreamDecoder *decoder);
-static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-static FLAC__bool seek_to_absolute_sample_(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
-
-/***********************************************************************
- *
- * Private class data
- *
- ***********************************************************************/
-
-typedef struct FLAC__SeekableStreamDecoderPrivate {
-       FLAC__SeekableStreamDecoderReadCallback read_callback;
-       FLAC__SeekableStreamDecoderSeekCallback seek_callback;
-       FLAC__SeekableStreamDecoderTellCallback tell_callback;
-       FLAC__SeekableStreamDecoderLengthCallback length_callback;
-       FLAC__SeekableStreamDecoderEofCallback eof_callback;
-       FLAC__SeekableStreamDecoderWriteCallback write_callback;
-       FLAC__SeekableStreamDecoderMetadataCallback metadata_callback;
-       FLAC__SeekableStreamDecoderErrorCallback error_callback;
-       void *client_data;
-       FLAC__StreamDecoder *stream_decoder;
-       FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek or if the metadata has a zero MD5 */
-       struct FLAC__MD5Context md5context;
-       FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
-       FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around for the md5sum comparison and also so we can figure out how to seek quickly */
-       FLAC__bool got_stream_info;
-       /* the rest of these are only used for seeking: */
-       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;
-       unsigned unparseable_frame_count; /* used to tell whether we're decoding a future version of FLAC or just got a bad sync */
-} FLAC__SeekableStreamDecoderPrivate;
-
-/***********************************************************************
- *
- * Public static class data
- *
- ***********************************************************************/
-
-FLAC_API const char * const FLAC__SeekableStreamDecoderStateString[] = {
-       "FLAC__SEEKABLE_STREAM_DECODER_OK",
-       "FLAC__SEEKABLE_STREAM_DECODER_SEEKING",
-       "FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM",
-       "FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
-       "FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR",
-       "FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR",
-       "FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR",
-       "FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED",
-       "FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK",
-       "FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED"
-};
-
-FLAC_API const char * const FLAC__SeekableStreamDecoderReadStatusString[] = {
-       "FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK",
-       "FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR"
-};
-
-FLAC_API const char * const FLAC__SeekableStreamDecoderSeekStatusString[] = {
-       "FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK",
-       "FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR"
-};
-
-FLAC_API const char * const FLAC__SeekableStreamDecoderTellStatusString[] = {
-       "FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK",
-       "FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR"
-};
-
-FLAC_API const char * const FLAC__SeekableStreamDecoderLengthStatusString[] = {
-       "FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK",
-       "FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR"
-};
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-FLAC_API FLAC__SeekableStreamDecoder *FLAC__seekable_stream_decoder_new()
-{
-       FLAC__SeekableStreamDecoder *decoder;
-
-       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
-
-       decoder = (FLAC__SeekableStreamDecoder*)calloc(1, sizeof(FLAC__SeekableStreamDecoder));
-       if(decoder == 0) {
-               return 0;
-       }
-
-       decoder->protected_ = (FLAC__SeekableStreamDecoderProtected*)calloc(1, sizeof(FLAC__SeekableStreamDecoderProtected));
-       if(decoder->protected_ == 0) {
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_ = (FLAC__SeekableStreamDecoderPrivate*)calloc(1, sizeof(FLAC__SeekableStreamDecoderPrivate));
-       if(decoder->private_ == 0) {
-               free(decoder->protected_);
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_->stream_decoder = FLAC__stream_decoder_new();
-       if(0 == decoder->private_->stream_decoder) {
-               free(decoder->private_);
-               free(decoder->protected_);
-               free(decoder);
-               return 0;
-       }
-
-       set_defaults_(decoder);
-
-       decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
-
-       return decoder;
-}
-
-FLAC_API void FLAC__seekable_stream_decoder_delete(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-
-       (void)FLAC__seekable_stream_decoder_finish(decoder);
-
-       FLAC__stream_decoder_delete(decoder->private_->stream_decoder);
-
-       free(decoder->private_);
-       free(decoder->protected_);
-       free(decoder);
-}
-
-/***********************************************************************
- *
- * Public class methods
- *
- ***********************************************************************/
-
-FLAC_API FLAC__SeekableStreamDecoderState FLAC__seekable_stream_decoder_init(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED;
-
-       if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback)
-               return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
-
-       if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
-               return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
-
-       decoder->private_->seek_table = 0;
-
-       decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
-       decoder->private_->got_stream_info = false;
-       decoder->private_->unparseable_frame_count = 0;
-
-       /* We initialize the FLAC__MD5Context even though we may never use it.  This
-        * is because md5 checking may be turned on to start and then turned off if
-        * a seek occurs.  So we always init the context here and finalize it in
-        * FLAC__seekable_stream_decoder_finish() to make sure things are always
-        * cleaned up properly.
-        */
-       FLAC__MD5Init(&decoder->private_->md5context);
-
-       FLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
-       FLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
-       FLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
-       FLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
-       FLAC__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...()
-        */
-       FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO);
-       FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
-
-       if(FLAC__stream_decoder_init(decoder->private_->stream_decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
-               return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_OK;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_finish(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool md5_failed = false;
-
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-
-       if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return true;
-
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-
-       /* see the comment in FLAC__seekable_stream_decoder_init() as to why we
-        * always call FLAC__MD5Final()
-        */
-       FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
-
-       FLAC__stream_decoder_finish(decoder->private_->stream_decoder);
-
-       if(decoder->private_->do_md5_checking) {
-               if(memcmp(decoder->private_->stream_info.md5sum, decoder->private_->computed_md5sum, 16))
-                       md5_failed = true;
-       }
-
-       set_defaults_(decoder);
-
-       decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
-
-       return !md5_failed;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_md5_checking(FLAC__SeekableStreamDecoder *decoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->protected_->md5_checking = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_read_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderReadCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->read_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_seek_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderSeekCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->seek_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_tell_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderTellCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->tell_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_length_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderLengthCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->length_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_eof_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderEofCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->eof_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_write_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->write_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderMetadataCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->metadata_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_error_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderErrorCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->error_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_client_data(FLAC__SeekableStreamDecoder *decoder, void *value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->client_data = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond(FLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       if(type == FLAC__METADATA_TYPE_STREAMINFO)
-               decoder->private_->ignore_stream_info_block = false;
-       else if(type == FLAC__METADATA_TYPE_SEEKTABLE)
-               decoder->private_->ignore_seek_table_block = false;
-       return FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond_application(FLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond_all(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->ignore_stream_info_block = false;
-       decoder->private_->ignore_seek_table_block = false;
-       return FLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore(FLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       if(type == FLAC__METADATA_TYPE_STREAMINFO) {
-               decoder->private_->ignore_stream_info_block = true;
-               return true;
-       }
-       else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
-               decoder->private_->ignore_seek_table_block = true;
-               return true;
-       }
-       else
-               return FLAC__stream_decoder_set_metadata_ignore(decoder->private_->stream_decoder, type);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore_application(FLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->stream_decoder, id);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore_all(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->ignore_stream_info_block = true;
-       decoder->private_->ignore_seek_table_block = true;
-       return
-               FLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->stream_decoder) &&
-               FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO) &&
-               FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
-}
-
-FLAC_API FLAC__SeekableStreamDecoderState FLAC__seekable_stream_decoder_get_state(const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       return decoder->protected_->state;
-}
-
-FLAC_API FLAC__StreamDecoderState FLAC__seekable_stream_decoder_get_stream_decoder_state(const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_state(decoder->private_->stream_decoder);
-}
-
-FLAC_API const char *FLAC__seekable_stream_decoder_get_resolved_state_string(const FLAC__SeekableStreamDecoder *decoder)
-{
-       if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR)
-               return FLAC__SeekableStreamDecoderStateString[decoder->protected_->state];
-       else
-               return FLAC__stream_decoder_get_resolved_state_string(decoder->private_->stream_decoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_get_md5_checking(const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       return decoder->protected_->md5_checking;
-}
-
-FLAC_API unsigned FLAC__seekable_stream_decoder_get_channels(const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_channels(decoder->private_->stream_decoder);
-}
-
-FLAC_API FLAC__ChannelAssignment FLAC__seekable_stream_decoder_get_channel_assignment(const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_channel_assignment(decoder->private_->stream_decoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_decoder_get_bits_per_sample(const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_bits_per_sample(decoder->private_->stream_decoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_decoder_get_sample_rate(const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_sample_rate(decoder->private_->stream_decoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_decoder_get_blocksize(const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_get_decode_position(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *position)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != position);
-
-       if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK)
-               return false;
-       FLAC__ASSERT(*position >= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder));
-       *position -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder);
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_flush(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-
-       decoder->private_->do_md5_checking = false;
-
-       if(!FLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-
-       decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_OK;
-
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_reset(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-
-       if(!FLAC__seekable_stream_decoder_flush(decoder)) {
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-
-       if(!FLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-
-       decoder->private_->seek_table = 0;
-
-       decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
-
-       /* We initialize the FLAC__MD5Context even though we may never use it.  This
-        * is because md5 checking may be turned on to start and then turned off if
-        * a seek occurs.  So we always init the context here and finalize it in
-        * FLAC__seekable_stream_decoder_finish() to make sure things are always
-        * cleaned up properly.
-        */
-       FLAC__MD5Init(&decoder->private_->md5context);
-
-       decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_OK;
-
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_single(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-
-       if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK);
-
-       ret = FLAC__stream_decoder_process_single(decoder->private_->stream_decoder);
-       if(!ret)
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_metadata(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-
-       if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK);
-
-       ret = FLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder);
-       if(!ret)
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_stream(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-
-       if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK);
-
-       ret = FLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder);
-       if(!ret)
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_skip_single_frame(FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-
-       if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK);
-
-       ret = FLAC__stream_decoder_skip_single_frame(decoder->private_->stream_decoder);
-       if(!ret)
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_decoder_seek_absolute(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample)
-{
-       FLAC__uint64 length;
-
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM);
-
-       decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEKING;
-
-       /* turn off md5 checking if a seek is attempted */
-       decoder->private_->do_md5_checking = false;
-
-       if(!FLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-       /* get the file length */
-       if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) {
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-               return false;
-       }
-       /* rewind */
-       if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-               return false;
-       }
-       if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) {
-               decoder->protected_->state = FLAC__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 = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-               return false;
-       }
-
-       return seek_to_absolute_sample_(decoder, length, sample);
-}
-
-/***********************************************************************
- *
- * Private class methods
- *
- ***********************************************************************/
-
-void set_defaults_(FLAC__SeekableStreamDecoder *decoder)
-{
-       decoder->private_->read_callback = 0;
-       decoder->private_->seek_callback = 0;
-       decoder->private_->tell_callback = 0;
-       decoder->private_->length_callback = 0;
-       decoder->private_->eof_callback = 0;
-       decoder->private_->write_callback = 0;
-       decoder->private_->metadata_callback = 0;
-       decoder->private_->error_callback = 0;
-       decoder->private_->client_data = 0;
-       /* WATCHOUT: these should match the default behavior of FLAC__StreamDecoder */
-       decoder->private_->ignore_stream_info_block = false;
-       decoder->private_->ignore_seek_table_block = true;
-
-       decoder->protected_->md5_checking = false;
-}
-
-FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-{
-       FLAC__SeekableStreamDecoder *seekable_stream_decoder = (FLAC__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 = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-#endif
-               return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-       }
-       else if(*bytes > 0) {
-               /* While seeking, it is possible for our seek to land in the
-                * middle of audio data that looks exactly like a frame header
-                * from a future version of an encoder.  When that happens, our
-                * error callback will get an
-                * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM and increment its
-                * unparseable_frame_count.  But there is a remote possibility
-                * that it is properly synced at such a "future-codec frame",
-                * so to make sure, we wait to see many "unparseable" errors in
-                * a row before bailing out.
-                */
-               if(seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_SEEKING && seekable_stream_decoder->private_->unparseable_frame_count > 20)
-                       return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
-               if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) {
-                       seekable_stream_decoder->protected_->state = FLAC__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 = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-#endif
-                               return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-                       }
-                       else
-                               return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-               }
-               else {
-                       return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-               }
-       }
-       else
-               return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
-}
-
-FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       FLAC__SeekableStreamDecoder *seekable_stream_decoder = (FLAC__SeekableStreamDecoder *)client_data;
-       (void)decoder;
-
-       if(seekable_stream_decoder->protected_->state == FLAC__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 = FLAC__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_->got_stream_info)
-                       seekable_stream_decoder->private_->do_md5_checking = false;
-               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 FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       FLAC__SeekableStreamDecoder *seekable_stream_decoder = (FLAC__SeekableStreamDecoder *)client_data;
-       (void)decoder;
-
-       if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
-               seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
-               seekable_stream_decoder->private_->got_stream_info = true;
-               if(0 == memcmp(seekable_stream_decoder->private_->stream_info.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 != FLAC__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 FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       FLAC__SeekableStreamDecoder *seekable_stream_decoder = (FLAC__SeekableStreamDecoder *)client_data;
-       (void)decoder;
-
-       if(seekable_stream_decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING)
-               seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
-       else if(status == FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM)
-               seekable_stream_decoder->private_->unparseable_frame_count++;
-}
-
-FLAC__bool seek_to_absolute_sample_(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
-{
-       FLAC__uint64 first_frame_offset, lower_bound, upper_bound;
-       FLAC__int64 pos = -1, last_pos = -1;
-       int i, lower_seek_point = -1, upper_seek_point = -1;
-       unsigned approx_bytes_per_frame;
-       FLAC__uint64 last_frame_sample = FLAC__U64L(0xffffffffffffffff);
-       FLAC__bool needs_seek;
-       const FLAC__uint64 total_samples = decoder->private_->stream_info.total_samples;
-       const unsigned min_blocksize = decoder->private_->stream_info.min_blocksize;
-       const unsigned max_blocksize = decoder->private_->stream_info.max_blocksize;
-       const unsigned max_framesize = decoder->private_->stream_info.max_framesize;
-       const unsigned channels = FLAC__seekable_stream_decoder_get_channels(decoder);
-       const unsigned bps = FLAC__seekable_stream_decoder_get_bits_per_sample(decoder);
-
-       /* we are just guessing here, but we want to guess high, not low */
-       if(max_framesize > 0) {
-               approx_bytes_per_frame = max_framesize;
-       }
-       /*
-        * Check if it's a known fixed-blocksize stream.  Note that though
-        * the spec doesn't allow zeroes in the STREAMINFO block, we may
-        * never get a STREAMINFO block when decoding so the value of
-        * min_blocksize might be zero.
-        */
-       else if(min_blocksize == max_blocksize && min_blocksize > 0) {
-               /* note there are no () around 'bps/8' to keep precision up since it's an integer calulation */
-               approx_bytes_per_frame = min_blocksize * channels * bps/8 + 64;
-       }
-       else
-               approx_bytes_per_frame = 4608 * channels * bps/8 + 64;
-
-       /*
-        * The decode position is currently at the first frame since we
-        * rewound and processed metadata.
-        */
-       if(!FLAC__seekable_stream_decoder_get_decode_position(decoder, &first_frame_offset)) {
-               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-               return false;
-       }
-
-       /*
-        * First, we set an upper and lower bound on where in the
-        * stream we will search.  For now we assume the worst case
-        * scenario, which is our best guess at the beginning of
-        * the first and last frames.
-        */
-       lower_bound = first_frame_offset;
-
-       /* calc the upper_bound, beyond which we never want to seek */
-       if(max_framesize > 0)
-               upper_bound = stream_length - (max_framesize + 128 + 2); /* 128 for a possible ID3V1 tag, 2 for indexing differences */
-       else
-               upper_bound = stream_length - ((channels * bps * FLAC__MAX_BLOCK_SIZE) / 8 + 128 + 2);
-
-       /*
-        * Now we refine the bounds if we have a seektable with
-        * suitable points.  Note that according to the spec they
-        * must be ordered by ascending sample number.
-        */
-       if(0 != decoder->private_->seek_table) {
-               /* find the closest seek point <= target_sample, if it exists */
-               for(i = (int)decoder->private_->seek_table->num_points - 1; i >= 0; i--) {
-                       if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number <= target_sample)
-                               break;
-               }
-               if(i >= 0) { /* i.e. we found a suitable seek point... */
-                       lower_bound = first_frame_offset + decoder->private_->seek_table->points[i].stream_offset;
-                       lower_seek_point = i;
-               }
-
-               /* find the closest seek point > target_sample, if it exists */
-               for(i = 0; i < (int)decoder->private_->seek_table->num_points; i++) {
-                       if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number > target_sample)
-                               break;
-               }
-               if(i < (int)decoder->private_->seek_table->num_points) { /* i.e. we found a suitable seek point... */
-                       upper_bound = first_frame_offset + decoder->private_->seek_table->points[i].stream_offset;
-                       upper_seek_point = i;
-               }
-       }
-
-       /*
-        * Now guess at where within those bounds our target
-        * sample will be.
-        */
-       if(lower_seek_point >= 0) {
-               /* first see if our sample is within a few frames of the lower seekpoint */
-               if(decoder->private_->seek_table->points[lower_seek_point].sample_number <= target_sample && target_sample < decoder->private_->seek_table->points[lower_seek_point].sample_number + (decoder->private_->seek_table->points[lower_seek_point].frame_samples * 4)) {
-                       pos = (FLAC__int64)lower_bound;
-               }
-               else if(upper_seek_point >= 0) {
-                       const FLAC__uint64 target_offset = target_sample - decoder->private_->seek_table->points[lower_seek_point].sample_number;
-                       const FLAC__uint64 range_samples = decoder->private_->seek_table->points[upper_seek_point].sample_number - decoder->private_->seek_table->points[lower_seek_point].sample_number;
-                       const FLAC__uint64 range_bytes = (upper_bound>lower_bound? upper_bound - lower_bound - 1 : 0);
-#ifndef FLAC__INTEGER_ONLY_LIBRARY
-#if defined _MSC_VER || defined __MINGW32__
-                       /* with MSVC you have to spoon feed it the casting */
-                       pos = (FLAC__int64)lower_bound + (FLAC__int64)(((FLAC__double)(FLAC__int64)target_offset / (FLAC__double)(FLAC__int64)range_samples) * (FLAC__double)(FLAC__int64)(range_bytes-1)) - approx_bytes_per_frame;
-#else
-                       pos = (FLAC__int64)lower_bound + (FLAC__int64)(((FLAC__double)target_offset / (FLAC__double)range_samples) * (FLAC__double)range_bytes) - approx_bytes_per_frame;
-#endif
-#else
-                       /* a little less accurate: */
-                       if (range_bytes <= 0xffffffff)
-                               pos = (FLAC__int64)lower_bound + (FLAC__int64)((target_offset * range_bytes) / range_samples) - approx_bytes_per_frame;
-                       else /* @@@ WATCHOUT, ~2TB limit */
-                               pos = (FLAC__int64)lower_bound + (FLAC__int64)(((target_offset>>8) * (range_bytes>>8)) / (range_samples>>16)) - approx_bytes_per_frame;
-#endif
-               }
-       }
-
-       /*
-        * If there's no seek table, we need to use the metadata (if we
-        * have it) and the filelength to estimate the position of the
-        * frame with the correct sample.
-        */
-       if(pos < 0 && total_samples > 0) {
-               /*
-                * For max accuracy we should be using
-                * (stream_length-first_frame_offset-1) in the divisor, but the
-                * difference is trivial and (stream_length-first_frame_offset)
-                * has no chance of underflow.
-                */
-#ifndef FLAC__INTEGER_ONLY_LIBRARY
-#if defined _MSC_VER || defined __MINGW32__
-               /* with VC++ you have to spoon feed it the casting */
-               pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((FLAC__double)(FLAC__int64)target_sample / (FLAC__double)(FLAC__int64)total_samples) * (FLAC__double)(FLAC__int64)(stream_length-first_frame_offset)) - approx_bytes_per_frame;
-#else
-               pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((FLAC__double)target_sample / (FLAC__double)total_samples) * (FLAC__double)(stream_length-first_frame_offset)) - approx_bytes_per_frame;
-#endif
-#else
-               /* a little less accurate: */
-               if (stream_length < 0xffffffff)
-                       pos = (FLAC__int64)first_frame_offset + (FLAC__int64)((target_sample * (stream_length-first_frame_offset)) / total_samples) - approx_bytes_per_frame;
-               else /* @@@ WATCHOUT, ~2TB limit */
-                       pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((target_sample>>8) * ((stream_length-first_frame_offset)>>8)) / (total_samples>>16)) - approx_bytes_per_frame;
-#endif
-       }
-
-       /*
-        * If there's no seek table and total_samples is unknown, we
-        * don't even bother trying to figure out a target, we just use
-        * our current position.
-        */
-       if(pos < 0) {
-               FLAC__uint64 upos;
-               if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) {
-                       decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                       return false;
-               }
-               pos = (FLAC__int64)upos;
-               needs_seek = false;
-       }
-       else
-               needs_seek = true;
-
-       /* clip the position to the bounds, lower bound takes precedence */
-       if(pos >= (FLAC__int64)upper_bound) {
-               pos = (FLAC__int64)upper_bound-1;
-               needs_seek = true;
-       }
-       if(pos < (FLAC__int64)lower_bound) {
-               pos = (FLAC__int64)lower_bound;
-               needs_seek = true;
-       }
-
-       decoder->private_->target_sample = target_sample;
-       while(1) {
-               if(needs_seek) {
-                       if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
-                               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                               return false;
-                       }
-                       if(!FLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
-                               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-                               return false;
-                       }
-               }
-               /* Now we need to get a frame.  First we need to reset our
-                * unparseable_frame_count; if we get too many unparseable
-                * frames in a row, the read callback will return
-                * FLAC__STREAM_DECODER_READ_STATUS_ABORT, causing
-                * FLAC__stream_decoder_process_single() to return false.
-                */
-               decoder->private_->unparseable_frame_count = 0;
-               if(!FLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
-                       decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                       return false;
-               }
-               /* our write callback will change the state when it gets to the target frame */
-               /* actually, we could have got_a_frame if our decoder is at FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM so we need to check for that also */
-               if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING && decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) {
-                       break;
-               }
-               else { /* we need to narrow the search */
-                       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 == last_frame_sample && pos < last_pos) {
-                               /* our last move backwards wasn't big enough, double it */
-                               pos -= (last_pos - pos);
-                               needs_seek = true;
-                       }
-                       else {
-                               if(target_sample < this_frame_sample) {
-                                       last_pos = pos;
-                                       approx_bytes_per_frame = decoder->private_->last_frame.header.blocksize * channels * bps/8 + 64;
-                                       pos -= approx_bytes_per_frame;
-                                       needs_seek = true;
-                               }
-                               else { /* target_sample >= this_frame_sample + this frame's blocksize */
-                                       FLAC__uint64 upos;
-                                       if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) {
-                                               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                                               return false;
-                                       }
-                                       last_pos = pos;
-                                       pos = (FLAC__int64)upos;
-                                       pos -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder);
-                                       needs_seek = false;
-                                       /*
-                                        * if we haven't hit the target frame yet and our position hasn't changed,
-                                        * it means we're at the end of the stream and the seek target does not exist.
-                                        */
-                                       if(last_pos == pos) {
-                                               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                                               return false;
-                                       }
-                               }
-                       }
-                       if(pos < (FLAC__int64)lower_bound)
-                               pos = (FLAC__int64)lower_bound;
-                       last_frame_sample = this_frame_sample;
-               }
-       }
-
-       return true;
-}
diff --git a/src/libFLAC/seekable_stream_encoder.c b/src/libFLAC/seekable_stream_encoder.c
deleted file mode 100644 (file)
index b943db7..0000000
+++ /dev/null
@@ -1,958 +0,0 @@
-/* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h> /* for calloc() */
-#include <string.h> /* for memcpy() */
-#include "FLAC/assert.h"
-#include "protected/seekable_stream_encoder.h"
-
-#ifdef max
-#undef max
-#endif
-#define max(a,b) ((a)>(b)?(a):(b))
-
-/***********************************************************************
- *
- * Private class method prototypes
- *
- ***********************************************************************/
-
-/* unpublished debug routines */
-extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-
-static void set_defaults_(FLAC__SeekableStreamEncoder *encoder);
-static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
-
-/***********************************************************************
- *
- * Private class data
- *
- ***********************************************************************/
-
-typedef struct FLAC__SeekableStreamEncoderPrivate {
-       FLAC__SeekableStreamEncoderSeekCallback seek_callback;
-       FLAC__SeekableStreamEncoderTellCallback tell_callback;
-       FLAC__SeekableStreamEncoderWriteCallback write_callback;
-       void *client_data;
-       FLAC__StreamEncoder *stream_encoder;
-       FLAC__StreamMetadata_SeekTable *seek_table;
-       /* internal vars (all the above are class settings) */
-       unsigned first_seekpoint_to_check;
-       FLAC__uint64 samples_written;
-} FLAC__SeekableStreamEncoderPrivate;
-
-/***********************************************************************
- *
- * Public static class data
- *
- ***********************************************************************/
-
-FLAC_API const char * const FLAC__SeekableStreamEncoderStateString[] = {
-       "FLAC__SEEKABLE_STREAM_ENCODER_OK",
-       "FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR",
-       "FLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
-       "FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR",
-       "FLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR",
-       "FLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR",
-       "FLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR",
-       "FLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED",
-       "FLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK",
-       "FLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE",
-       "FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED"
-};
-
-FLAC_API const char * const FLAC__SeekableStreamEncoderSeekStatusString[] = {
-       "FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK",
-       "FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR"
-};
-
-FLAC_API const char * const FLAC__SeekableStreamEncoderTellStatusString[] = {
-       "FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK",
-       "FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_ERROR"
-};
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-FLAC_API FLAC__SeekableStreamEncoder *FLAC__seekable_stream_encoder_new()
-{
-       FLAC__SeekableStreamEncoder *encoder;
-
-       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
-
-       encoder = (FLAC__SeekableStreamEncoder*)calloc(1, sizeof(FLAC__SeekableStreamEncoder));
-       if(encoder == 0) {
-               return 0;
-       }
-
-       encoder->protected_ = (FLAC__SeekableStreamEncoderProtected*)calloc(1, sizeof(FLAC__SeekableStreamEncoderProtected));
-       if(encoder->protected_ == 0) {
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_ = (FLAC__SeekableStreamEncoderPrivate*)calloc(1, sizeof(FLAC__SeekableStreamEncoderPrivate));
-       if(encoder->private_ == 0) {
-               free(encoder->protected_);
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_->stream_encoder = FLAC__stream_encoder_new();
-       if(0 == encoder->private_->stream_encoder) {
-               free(encoder->private_);
-               free(encoder->protected_);
-               free(encoder);
-               return 0;
-       }
-
-       set_defaults_(encoder);
-
-       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED;
-
-       return encoder;
-}
-
-FLAC_API void FLAC__seekable_stream_encoder_delete(FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-
-       (void)FLAC__seekable_stream_encoder_finish(encoder);
-
-       FLAC__stream_encoder_delete(encoder->private_->stream_encoder);
-
-       free(encoder->private_);
-       free(encoder->protected_);
-       free(encoder);
-}
-
-
-/***********************************************************************
- *
- * Public class methods
- *
- ***********************************************************************/
-
-FLAC_API FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_init(FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED;
-
-       if(0 == encoder->private_->seek_callback || 0 == encoder->private_->tell_callback || 0 == encoder->private_->write_callback)
-               return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK;
-
-       if(0 != encoder->private_->seek_table && !FLAC__format_seektable_is_legal(encoder->private_->seek_table))
-               return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE;
-
-       /*
-        * These must be done before we init the stream encoder because that
-        * calls the write_callback, which uses these values.
-        */
-       encoder->private_->first_seekpoint_to_check = 0;
-       encoder->private_->samples_written = 0;
-       encoder->protected_->streaminfo_offset = 0;
-       encoder->protected_->seektable_offset = 0;
-       encoder->protected_->audio_offset = 0;
-
-       FLAC__stream_encoder_set_write_callback(encoder->private_->stream_encoder, write_callback_);
-       FLAC__stream_encoder_set_metadata_callback(encoder->private_->stream_encoder, metadata_callback_);
-       FLAC__stream_encoder_set_client_data(encoder->private_->stream_encoder, encoder);
-
-       if(FLAC__stream_encoder_init(encoder->private_->stream_encoder) != FLAC__STREAM_ENCODER_OK)
-               return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR;
-
-       /*
-        * Initializing the stream encoder writes all the metadata, so we
-        * save the stream offset now.
-        */
-       if(encoder->private_->tell_callback(encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK)
-               return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR;
-
-       return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_OK;
-}
-
-FLAC_API void FLAC__seekable_stream_encoder_finish(FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-
-       if(encoder->protected_->state == FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return;
-
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-
-       FLAC__stream_encoder_finish(encoder->private_->stream_encoder);
-
-       set_defaults_(encoder);
-
-       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_verify(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_verify(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_streamable_subset(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_streamable_subset(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_do_mid_side_stereo(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_channels(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_channels(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_bits_per_sample(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_sample_rate(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_sample_rate(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_blocksize(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_blocksize(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_apodization(FLAC__SeekableStreamEncoder *encoder, const char *specification)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_apodization(encoder->private_->stream_encoder, specification);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_max_lpc_order(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_qlp_coeff_precision(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_do_escape_coding(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_min_residual_partition_order(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_max_residual_partition_order(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_rice_parameter_search_dist(FLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_total_samples_estimate(FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_metadata(FLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->stream_encoder);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       if(0 != metadata && num_blocks > 0) {
-               unsigned i;
-               for(i = 0; i < num_blocks; i++) {
-                       if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
-                               encoder->private_->seek_table = &metadata[i]->data.seek_table;
-                               break; /* take only the first one */
-                       }
-               }
-       }
-       return FLAC__stream_encoder_set_metadata(encoder->private_->stream_encoder, metadata, num_blocks);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_seek_callback(FLAC__SeekableStreamEncoder *encoder, FLAC__SeekableStreamEncoderSeekCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->seek_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_tell_callback(FLAC__SeekableStreamEncoder *encoder, FLAC__SeekableStreamEncoderTellCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->tell_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_write_callback(FLAC__SeekableStreamEncoder *encoder, FLAC__SeekableStreamEncoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->write_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_set_client_data(FLAC__SeekableStreamEncoder *encoder, void *value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->client_data = value;
-       return true;
-}
-
-/*
- * These three functions are not static, but not publically exposed in
- * include/FLAC/ either.  They are used by the test suite.
- */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_disable_constant_subframes(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_disable_constant_subframes(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_disable_fixed_subframes(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_disable_fixed_subframes(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_disable_verbatim_subframes(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_disable_verbatim_subframes(encoder->private_->stream_encoder, value);
-}
-
-FLAC_API FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_get_state(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->protected_);
-       return encoder->protected_->state;
-}
-
-FLAC_API FLAC__StreamEncoderState FLAC__seekable_stream_encoder_get_stream_encoder_state(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_state(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__StreamDecoderState FLAC__seekable_stream_encoder_get_verify_decoder_state(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->stream_encoder);
-}
-
-FLAC_API const char *FLAC__seekable_stream_encoder_get_resolved_state_string(const FLAC__SeekableStreamEncoder *encoder)
-{
-       if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR)
-               return FLAC__SeekableStreamEncoderStateString[encoder->protected_->state];
-       else
-               return FLAC__stream_encoder_get_resolved_state_string(encoder->private_->stream_encoder);
-}
-
-FLAC_API void FLAC__seekable_stream_encoder_get_verify_decoder_error_stats(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__stream_encoder_get_verify_decoder_error_stats(encoder->private_->stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_verify(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_verify(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_streamable_subset(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_streamable_subset(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_do_mid_side_stereo(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_loose_mid_side_stereo(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_channels(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_channels(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_bits_per_sample(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_sample_rate(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_sample_rate(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_blocksize(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_blocksize(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_max_lpc_order(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_qlp_coeff_precision(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_do_escape_coding(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_get_do_exhaustive_model_search(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_min_residual_partition_order(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_max_residual_partition_order(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->stream_encoder);
-}
-
-FLAC_API unsigned FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__uint64 FLAC__seekable_stream_encoder_get_total_samples_estimate(const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->stream_encoder);
-}
-
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_process(FLAC__SeekableStreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       if(!FLAC__stream_encoder_process(encoder->private_->stream_encoder, buffer, samples)) {
-               encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR;
-               return false;
-       }
-       else
-               return true;
-}
-
-/* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
-FLAC_API FLAC__bool FLAC__seekable_stream_encoder_process_interleaved(FLAC__SeekableStreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       if(!FLAC__stream_encoder_process_interleaved(encoder->private_->stream_encoder, buffer, samples)) {
-               encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR;
-               return false;
-       }
-       else
-               return true;
-}
-
-/***********************************************************************
- *
- * Private class methods
- *
- ***********************************************************************/
-
-void set_defaults_(FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-
-       encoder->private_->seek_callback = 0;
-       encoder->private_->tell_callback = 0;
-       encoder->private_->write_callback = 0;
-       encoder->private_->client_data = 0;
-
-       encoder->private_->seek_table = 0;
-}
-
-FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       FLAC__SeekableStreamEncoder *encoder = (FLAC__SeekableStreamEncoder*)client_data;
-       FLAC__StreamEncoderWriteStatus status;
-       FLAC__uint64 output_position;
-
-       (void)unused; /* silence compiler warning about unused parameter */
-       FLAC__ASSERT(encoder->private_->stream_encoder == unused);
-
-       if(encoder->private_->tell_callback(encoder, &output_position, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK)
-               return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR;
-
-       /*
-        * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets.
-        */
-       if(samples == 0) {
-               FLAC__MetadataType type = (buffer[0] & 0x7f);
-               if(type == FLAC__METADATA_TYPE_STREAMINFO)
-                       encoder->protected_->streaminfo_offset = output_position;
-               else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0)
-                       encoder->protected_->seektable_offset = output_position;
-       }
-
-       /*
-        * Mark the current seek point if hit (if audio_offset == 0 that
-        * means we're still writing metadata and haven't hit the first
-        * frame yet)
-        */
-       if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) {
-               const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder->private_->stream_encoder);
-               const FLAC__uint64 frame_first_sample = encoder->private_->samples_written;
-               const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
-               FLAC__uint64 test_sample;
-               unsigned i;
-               for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) {
-                       test_sample = encoder->private_->seek_table->points[i].sample_number;
-                       if(test_sample > frame_last_sample) {
-                               break;
-                       }
-                       else if(test_sample >= frame_first_sample) {
-                               encoder->private_->seek_table->points[i].sample_number = frame_first_sample;
-                               encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset;
-                               encoder->private_->seek_table->points[i].frame_samples = blocksize;
-                               encoder->private_->first_seekpoint_to_check++;
-                               /* DO NOT: "break;" and here's why:
-                                * The seektable template may contain more than one target
-                                * sample for any given frame; we will keep looping, generating
-                                * duplicate seekpoints for them, and we'll clean it up later,
-                                * just before writing the seektable back to the metadata.
-                                */
-                       }
-                       else {
-                               encoder->private_->first_seekpoint_to_check++;
-                       }
-               }
-       }
-
-       status = encoder->private_->write_callback(encoder, buffer, bytes, samples, current_frame, encoder->private_->client_data);
-
-       if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
-               encoder->private_->samples_written += samples;
-       }
-       else
-               encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
-
-       return status;
-}
-
-void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       FLAC__SeekableStreamEncoder *encoder = (FLAC__SeekableStreamEncoder*)client_data;
-       FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)];
-       const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
-       const unsigned min_framesize = metadata->data.stream_info.min_framesize;
-       const unsigned max_framesize = metadata->data.stream_info.max_framesize;
-       const unsigned bps = metadata->data.stream_info.bits_per_sample;
-
-       FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
-
-       /* We get called by the stream encoder when the encoding process
-        * has finished so that we can update the STREAMINFO and SEEKTABLE
-        * blocks.
-        */
-
-       (void)unused; /* silence compiler warning about unused parameter */
-       FLAC__ASSERT(encoder->private_->stream_encoder == unused);
-
-       /*@@@ reopen callback here?  The docs currently require user to open files in update mode from the start */
-
-       /* All this is based on intimate knowledge of the stream header
-        * layout, but a change to the header format that would break this
-        * would also break all streams encoded in the previous format.
-        */
-
-       /*
-        * Write MD5 signature
-        */
-       {
-               const unsigned md5_offset =
-               FLAC__STREAM_METADATA_HEADER_LENGTH +
-               (
-                       FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
-               ) / 8;
-
-               if(encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + md5_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
-                       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
-                       return;
-               }
-               if(encoder->private_->write_callback(encoder, metadata->data.stream_info.md5sum, 16, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
-                       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
-                       return;
-               }
-       }
-
-       /*
-        * Write total samples
-        */
-       {
-               const unsigned total_samples_byte_offset =
-               FLAC__STREAM_METADATA_HEADER_LENGTH +
-               (
-                       FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
-                       - 4
-               ) / 8;
-
-               b[0] = ((FLAC__byte)(bps-1) << 4) | (FLAC__byte)((samples >> 32) & 0x0F);
-               b[1] = (FLAC__byte)((samples >> 24) & 0xFF);
-               b[2] = (FLAC__byte)((samples >> 16) & 0xFF);
-               b[3] = (FLAC__byte)((samples >> 8) & 0xFF);
-               b[4] = (FLAC__byte)(samples & 0xFF);
-               if(encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + total_samples_byte_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
-                       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
-                       return;
-               }
-               if(encoder->private_->write_callback(encoder, b, 5, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
-                       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
-                       return;
-               }
-       }
-
-       /*
-        * Write min/max framesize
-        */
-       {
-               const unsigned min_framesize_offset =
-               FLAC__STREAM_METADATA_HEADER_LENGTH +
-               (
-                       FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
-                       FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
-               ) / 8;
-
-               b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF);
-               b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF);
-               b[2] = (FLAC__byte)(min_framesize & 0xFF);
-               b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF);
-               b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF);
-               b[5] = (FLAC__byte)(max_framesize & 0xFF);
-               if(encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + min_framesize_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
-                       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
-                       return;
-               }
-               if(encoder->private_->write_callback(encoder, b, 6, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
-                       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
-                       return;
-               }
-       }
-
-       /*
-        * Write seektable
-        */
-       if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) {
-               unsigned i;
-
-               FLAC__format_seektable_sort(encoder->private_->seek_table);
-
-               FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table));
-
-               if(encoder->private_->seek_callback(encoder, encoder->protected_->seektable_offset + FLAC__STREAM_METADATA_HEADER_LENGTH, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
-                       encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
-                       return;
-               }
-
-               for(i = 0; i < encoder->private_->seek_table->num_points; i++) {
-                       FLAC__uint64 xx;
-                       unsigned x;
-                       xx = encoder->private_->seek_table->points[i].sample_number;
-                       b[7] = (FLAC__byte)xx; xx >>= 8;
-                       b[6] = (FLAC__byte)xx; xx >>= 8;
-                       b[5] = (FLAC__byte)xx; xx >>= 8;
-                       b[4] = (FLAC__byte)xx; xx >>= 8;
-                       b[3] = (FLAC__byte)xx; xx >>= 8;
-                       b[2] = (FLAC__byte)xx; xx >>= 8;
-                       b[1] = (FLAC__byte)xx; xx >>= 8;
-                       b[0] = (FLAC__byte)xx; xx >>= 8;
-                       xx = encoder->private_->seek_table->points[i].stream_offset;
-                       b[15] = (FLAC__byte)xx; xx >>= 8;
-                       b[14] = (FLAC__byte)xx; xx >>= 8;
-                       b[13] = (FLAC__byte)xx; xx >>= 8;
-                       b[12] = (FLAC__byte)xx; xx >>= 8;
-                       b[11] = (FLAC__byte)xx; xx >>= 8;
-                       b[10] = (FLAC__byte)xx; xx >>= 8;
-                       b[9] = (FLAC__byte)xx; xx >>= 8;
-                       b[8] = (FLAC__byte)xx; xx >>= 8;
-                       x = encoder->private_->seek_table->points[i].frame_samples;
-                       b[17] = (FLAC__byte)x; x >>= 8;
-                       b[16] = (FLAC__byte)x; x >>= 8;
-                       if(encoder->private_->write_callback(encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
-                               encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
-                               return;
-                       }
-               }
-       }
-}
index b3ac1a8..3f3e906 100644 (file)
 #  include <config.h>
 #endif
 
+#if defined _MSC_VER || defined __MINGW32__
+#include <io.h> /* for _setmode() */
+#include <fcntl.h> /* for _O_BINARY */
+#endif
+#if defined __CYGWIN__ || defined __EMX__
+#include <io.h> /* for setmode(), O_BINARY */
+#include <fcntl.h> /* for _O_BINARY */
+#endif
 #include <stdio.h>
 #include <stdlib.h> /* for malloc() */
 #include <string.h> /* for memset/memcpy() */
+#include <sys/stat.h> /* for stat() */
+#include <sys/types.h> /* for off_t */
+#if defined _MSC_VER || defined __MINGW32__
+/*@@@ [2G limit] hacks for MSVC6 */
+#define fseeko fseek
+#define ftello ftell
+#endif
 #include "FLAC/assert.h"
 #include "protected/stream_decoder.h"
 #include "private/bitbuffer.h"
 #include "private/fixed.h"
 #include "private/format.h"
 #include "private/lpc.h"
+#include "private/md5.h"
 #include "private/memory.h"
 
+#undef OLD_STAT_WAY /*@@@@@@ old way of keeping the filename and using stat(); remove remnants once we know this works */
+
 #ifdef max
 #undef max
 #endif
@@ -74,6 +92,7 @@ static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' };
  ***********************************************************************/
 
 static void set_defaults_(FLAC__StreamDecoder *decoder);
+static FILE *get_binary_stdin_();
 static FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels);
 static FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id);
 static FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder);
@@ -94,6 +113,14 @@ static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned
 static FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual);
 static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder);
 static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
+static void send_error_to_client_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status);
+static FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
+static FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+static FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+static FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
+static FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data);
 
 /***********************************************************************
  *
@@ -103,6 +130,10 @@ static FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *cli
 
 typedef struct FLAC__StreamDecoderPrivate {
        FLAC__StreamDecoderReadCallback read_callback;
+       FLAC__StreamDecoderSeekCallback seek_callback;
+       FLAC__StreamDecoderTellCallback tell_callback;
+       FLAC__StreamDecoderLengthCallback length_callback;
+       FLAC__StreamDecoderEofCallback eof_callback;
        FLAC__StreamDecoderWriteCallback write_callback;
        FLAC__StreamDecoderMetadataCallback metadata_callback;
        FLAC__StreamDecoderErrorCallback error_callback;
@@ -115,6 +146,10 @@ typedef struct FLAC__StreamDecoderPrivate {
        /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit), AND order <= 8: */
        void (*local_lpc_restore_signal_16bit_order8)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
        void *client_data;
+       FILE *file; /* only used if FLAC__stream_decoder_init_file()/FLAC__stream_decoder_init_file() called, else NULL */
+#ifdef OLD_STAT_WAY
+       char *filename; /* only used if FLAC__stream_decoder_init_file()/FLAC__stream_decoder_init_file() called, else NULL */
+#endif
        FLAC__BitBuffer *input;
        FLAC__int32 *output[FLAC__MAX_CHANNELS];
        FLAC__int32 *residual[FLAC__MAX_CHANNELS]; /* WATCHOUT: these are the aligned pointers; the real pointers that should be free()'d are residual_unaligned[] below */
@@ -136,6 +171,16 @@ typedef struct FLAC__StreamDecoderPrivate {
        FLAC__byte lookahead; /* temp storage when we need to look ahead one byte in the stream */
        /* unaligned (original) pointers to allocated data */
        FLAC__int32 *residual_unaligned[FLAC__MAX_CHANNELS];
+       FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek or if the metadata has a zero MD5 */
+       FLAC__bool internal_reset_hack; /* used only during init() so we can call reset to set up the decoder without rewinding the input */
+       FLAC__bool is_seeking;
+       struct FLAC__MD5Context md5context;
+       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__Frame last_frame; /* holds the info of the last frame we seeked to */
+       FLAC__uint64 first_frame_offset; /* hint to the seek routine of where in the stream the first audio frame starts */
+       FLAC__uint64 target_sample;
+       unsigned unparseable_frame_count; /* used to tell whether we're decoding a future version of FLAC or just got a bad sync */
 } FLAC__StreamDecoderPrivate;
 
 /***********************************************************************
@@ -150,19 +195,44 @@ FLAC_API const char * const FLAC__StreamDecoderStateString[] = {
        "FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC",
        "FLAC__STREAM_DECODER_READ_FRAME",
        "FLAC__STREAM_DECODER_END_OF_STREAM",
+       "FLAC__STREAM_DECODER_SEEK_ERROR",
        "FLAC__STREAM_DECODER_ABORTED",
        "FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
-       "FLAC__STREAM_DECODER_ALREADY_INITIALIZED",
-       "FLAC__STREAM_DECODER_INVALID_CALLBACK",
        "FLAC__STREAM_DECODER_UNINITIALIZED"
 };
 
+FLAC_API const char * const FLAC__StreamDecoderInitStatusString[] = {
+       "FLAC__STREAM_DECODER_INIT_STATUS_OK",
+       "FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS",
+       "FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR",
+       "FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE",
+       "FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED"
+};
+
 FLAC_API const char * const FLAC__StreamDecoderReadStatusString[] = {
        "FLAC__STREAM_DECODER_READ_STATUS_CONTINUE",
        "FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM",
        "FLAC__STREAM_DECODER_READ_STATUS_ABORT"
 };
 
+FLAC_API const char * const FLAC__StreamDecoderSeekStatusString[] = {
+       "FLAC__STREAM_DECODER_SEEK_STATUS_OK",
+       "FLAC__STREAM_DECODER_SEEK_STATUS_ERROR",
+       "FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED"
+};
+
+FLAC_API const char * const FLAC__StreamDecoderTellStatusString[] = {
+       "FLAC__STREAM_DECODER_TELL_STATUS_OK",
+       "FLAC__STREAM_DECODER_TELL_STATUS_ERROR",
+       "FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED"
+};
+
+FLAC_API const char * const FLAC__StreamDecoderLengthStatusString[] = {
+       "FLAC__STREAM_DECODER_LENGTH_STATUS_OK",
+       "FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR",
+       "FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED"
+};
+
 FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[] = {
        "FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE",
        "FLAC__STREAM_DECODER_WRITE_STATUS_ABORT"
@@ -234,6 +304,8 @@ FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new()
        for(i = 0; i < FLAC__MAX_CHANNELS; i++)
                FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&decoder->private_->partitioned_rice_contents[i]);
 
+       decoder->private_->file = 0;
+
        set_defaults_(decoder);
 
        decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
@@ -271,24 +343,31 @@ FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder)
  *
  ***********************************************************************/
 
-FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder *decoder)
+FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
+       FLAC__StreamDecoder *decoder,
+       FLAC__StreamDecoderReadCallback read_callback,
+       FLAC__StreamDecoderSeekCallback seek_callback,
+       FLAC__StreamDecoderTellCallback tell_callback,
+       FLAC__StreamDecoderLengthCallback length_callback,
+       FLAC__StreamDecoderEofCallback eof_callback,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+)
 {
        FLAC__ASSERT(0 != decoder);
 
        if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
-               return decoder->protected_->state = FLAC__STREAM_DECODER_ALREADY_INITIALIZED;
-
-       if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
-               return decoder->protected_->state = FLAC__STREAM_DECODER_INVALID_CALLBACK;
-
-       if(!FLAC__bitbuffer_init(decoder->private_->input))
-               return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+               return FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED;
 
-       decoder->private_->last_frame_number = 0;
-       decoder->private_->last_block_size = 0;
-       decoder->private_->samples_decoded = 0;
-       decoder->private_->has_stream_info = false;
-       decoder->private_->cached = false;
+       if(
+               0 == read_callback ||
+               0 == write_callback ||
+               0 == error_callback ||
+               (seek_callback && (0 == tell_callback || 0 == length_callback || 0 == eof_callback))
+       )
+               return FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS;
 
        /*
         * get the CPU info and set the function pointers
@@ -326,19 +405,158 @@ FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder
        }
 #endif
 
-       if(!FLAC__stream_decoder_reset(decoder))
-               return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+       /* from here on, errors are fatal */
 
-       return decoder->protected_->state;
+       if(!FLAC__bitbuffer_init(decoder->private_->input)) {
+               decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+               return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR;
+       }
+
+       decoder->private_->read_callback = read_callback;
+       decoder->private_->seek_callback = seek_callback;
+       decoder->private_->tell_callback = tell_callback;
+       decoder->private_->length_callback = length_callback;
+       decoder->private_->eof_callback = eof_callback;
+       decoder->private_->write_callback = write_callback;
+       decoder->private_->metadata_callback = metadata_callback;
+       decoder->private_->error_callback = error_callback;
+       decoder->private_->client_data = client_data;
+       decoder->private_->last_frame_number = 0;
+       decoder->private_->last_block_size = 0;
+       decoder->private_->samples_decoded = 0;
+       decoder->private_->has_stream_info = false;
+       decoder->private_->cached = false;
+
+       decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
+       decoder->private_->is_seeking = false;
+
+       decoder->private_->internal_reset_hack = true; /* so the following reset does not try to rewind the input */
+       if(!FLAC__stream_decoder_reset(decoder)) {
+               /* above call sets the state for us */
+               return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR;
+       }
+
+       return FLAC__STREAM_DECODER_INIT_STATUS_OK;
+}
+
+FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
+       FLAC__StreamDecoder *decoder,
+       FILE *file,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+)
+{
+       FLAC__ASSERT(0 != decoder);
+       FLAC__ASSERT(0 != file);
+
+       if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED;
+
+       if(0 == write_callback || 0 == error_callback)
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS;
+
+       /*
+        * To make sure that our file does not go unclosed after an error, we
+        * must assign the FILE pointer before any further error can occur in
+        * this routine.
+        */
+       if(file == stdin)
+               file = get_binary_stdin_(); /* just to be safe */
+
+       decoder->private_->file = file;
+
+#ifdef OLD_STAT_WAY
+       if(0 != decoder->private_->filename) {
+               free(decoder->private_->filename);
+               decoder->private_->filename = 0;
+       }
+       if(filename) {
+               if(0 == (decoder->private_->filename = strdup(filename))) {
+                       decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+                       return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR;
+               }
+       }
+#endif
+
+       return FLAC__stream_decoder_init_stream(
+               decoder,
+               file_read_callback_,
+               decoder->private_->file == stdin? 0: file_seek_callback_,
+               decoder->private_->file == stdin? 0: file_tell_callback_,/*@@@@@@ might work for stdin*/
+               decoder->private_->file == stdin? 0: file_length_callback_,
+               decoder->private_->file == stdin? 0: file_eof_callback_,/*@@@@@@ might work for stdin*/
+               write_callback,
+               metadata_callback,
+               error_callback,
+               client_data
+       );
+}
+
+FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
+       FLAC__StreamDecoder *decoder,
+       const char *filename,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+)
+{
+       FILE *file;
+
+       FLAC__ASSERT(0 != decoder);
+
+       /*
+        * To make sure that our file does not go unclosed after an error, we
+        * have to do the same entrance checks here that are later performed
+        * in FLAC__stream_decoder_init_FILE() before the FILE* is assigned.
+        */
+       if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED;
+
+       if(0 == write_callback || 0 == error_callback)
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS;
+
+       file = filename? fopen(filename, "rb") : stdin;
+
+       if(0 == file)
+               return FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE;
+
+#ifdef OLD_STAT_WAY
+       if(0 != decoder->private_->filename) {
+               free(decoder->private_->filename);
+               decoder->private_->filename = 0;
+       }
+       if(filename) {
+               if(0 == (decoder->private_->filename = strdup(filename))) {
+                       decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+                       return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR;
+               }
+       }
+#endif
+
+       return FLAC__stream_decoder_init_FILE(decoder, file, write_callback, metadata_callback, error_callback, client_data);
 }
 
-FLAC_API void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
+FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
 {
+       FLAC__bool md5_failed = false;
        unsigned i;
+
        FLAC__ASSERT(0 != decoder);
+       FLAC__ASSERT(0 != decoder->private_);
+       FLAC__ASSERT(0 != decoder->protected_);
+
        if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED)
-               return;
-       if(0 != decoder->private_->seek_table.data.seek_table.points) {
+               return true;
+
+       /* see the comment in FLAC__seekable_stream_decoder_reset() as to why we
+        * always call FLAC__MD5Final()
+        */
+       FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
+
+       if(decoder->private_->has_seek_table && 0 != decoder->private_->seek_table.data.seek_table.points) {
                free(decoder->private_->seek_table.data.seek_table.points);
                decoder->private_->seek_table.data.seek_table.points = 0;
                decoder->private_->has_seek_table = false;
@@ -363,63 +581,38 @@ FLAC_API void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
        decoder->private_->output_capacity = 0;
        decoder->private_->output_channels = 0;
 
-       set_defaults_(decoder);
+       if(0 != decoder->private_->file && decoder->private_->file != stdin) {
+               fclose(decoder->private_->file);
+               decoder->private_->file = 0;
+       }
 
-       decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
-}
+#ifdef OLD_STAT_WAY
+       if(0 != decoder->private_->filename) {
+               free(decoder->private_->filename);
+               decoder->private_->filename = 0;
+       }
+#endif
 
-FLAC_API FLAC__bool FLAC__stream_decoder_set_read_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->read_callback = value;
-       return true;
-}
+       if(decoder->private_->do_md5_checking) {
+               if(memcmp(decoder->private_->stream_info.data.stream_info.md5sum, decoder->private_->computed_md5sum, 16))
+                       md5_failed = true;
+       }
+       decoder->private_->is_seeking = false;
 
-FLAC_API FLAC__bool FLAC__stream_decoder_set_write_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->write_callback = value;
-       return true;
-}
+       set_defaults_(decoder);
 
-FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderMetadataCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->metadata_callback = value;
-       return true;
-}
+       decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
 
-FLAC_API FLAC__bool FLAC__stream_decoder_set_error_callback(FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->error_callback = value;
-       return true;
+       return !md5_failed;
 }
 
-FLAC_API FLAC__bool FLAC__stream_decoder_set_client_data(FLAC__StreamDecoder *decoder, void *value)
+FLAC_API FLAC__bool FLAC__stream_decoder_set_md5_checking(FLAC__StreamDecoder *decoder, FLAC__bool value)
 {
        FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
                return false;
-       decoder->private_->client_data = value;
+       decoder->protected_->md5_checking = value;
        return true;
 }
 
@@ -551,6 +744,20 @@ FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__
        return FLAC__StreamDecoderStateString[decoder->protected_->state];
 }
 
+FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDecoder *decoder)
+{
+       FLAC__ASSERT(0 != decoder);
+       FLAC__ASSERT(0 != decoder->protected_);
+       return decoder->protected_->md5_checking;
+}
+
+FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder)
+{
+       FLAC__ASSERT(0 != decoder);
+       FLAC__ASSERT(0 != decoder->protected_);
+       return decoder->private_->has_stream_info? decoder->private_->stream_info.data.stream_info.total_samples : 0;
+}
+
 FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(0 != decoder);
@@ -586,12 +793,30 @@ FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *
        return decoder->protected_->blocksize;
 }
 
+FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position)
+{
+       FLAC__ASSERT(0 != decoder);
+       FLAC__ASSERT(0 != decoder->private_);
+       FLAC__ASSERT(0 != position);
+
+       if(0 == decoder->private_->tell_callback)
+               return false;
+       if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != FLAC__STREAM_DECODER_TELL_STATUS_OK)
+               return false;
+       FLAC__ASSERT(*position >= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder));
+       *position -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder);
+       return true;
+}
+
 FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
        FLAC__ASSERT(0 != decoder->protected_);
 
+       decoder->private_->samples_decoded = 0;
+       decoder->private_->do_md5_checking = false;
+
        if(!FLAC__bitbuffer_clear(decoder->private_->input)) {
                decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
                return false;
@@ -610,12 +835,44 @@ FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder)
        FLAC__ASSERT(0 != decoder->protected_);
 
        if(!FLAC__stream_decoder_flush(decoder)) {
-               decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+               /* above call sets the state for us */
                return false;
        }
+
+       /* Rewind if necessary.  If FLAC__stream_decoder_init() is calling us,
+        * (internal_reset_hack) don't try to rewind since we are already at
+        * the beginning of the stream and don't want to fail if the input is
+        * not seekable.
+        */
+       if(!decoder->private_->internal_reset_hack) {
+               if(decoder->private_->file == stdin)
+                       return false; /* can't rewind stdin, reset fails */
+               if(decoder->private_->seek_callback && decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) == FLAC__STREAM_DECODER_SEEK_STATUS_ERROR)
+                       return false; /* seekable and seek fails, reset fails */
+       }
+       else
+               decoder->private_->internal_reset_hack = false;
+
        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
 
-       decoder->private_->samples_decoded = 0;
+       decoder->private_->has_stream_info = false;
+       if(decoder->private_->has_seek_table && 0 != decoder->private_->seek_table.data.seek_table.points) {
+               free(decoder->private_->seek_table.data.seek_table.points);
+               decoder->private_->seek_table.data.seek_table.points = 0;
+               decoder->private_->has_seek_table = false;
+       }
+       decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
+
+       /* We initialize the FLAC__MD5Context even though we may never use it.  This
+        * is because md5 checking may be turned on to start and then turned off if
+        * a seek occurs.  So we init the context here and finalize it in
+        * FLAC__seekable_stream_decoder_finish() to make sure things are always
+        * cleaned up properly.
+        */
+       FLAC__MD5Init(&decoder->private_->md5context);
+
+       decoder->private_->first_frame_offset = 0;
+       decoder->private_->unparseable_frame_count = 0;
 
        return true;
 }
@@ -749,6 +1006,66 @@ FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *
        }
 }
 
+FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *decoder, FLAC__uint64 sample)
+{
+       FLAC__uint64 length;
+
+       FLAC__ASSERT(0 != decoder);
+
+       if(
+               decoder->protected_->state != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA &&
+               decoder->protected_->state != FLAC__STREAM_DECODER_READ_METADATA &&
+               decoder->protected_->state != FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC &&
+               decoder->protected_->state != FLAC__STREAM_DECODER_READ_FRAME &&
+               decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM
+       )
+               return false;
+
+       if(0 == decoder->private_->seek_callback)
+               return false;
+
+       FLAC__ASSERT(decoder->private_->seek_callback);
+       FLAC__ASSERT(decoder->private_->tell_callback);
+       FLAC__ASSERT(decoder->private_->length_callback);
+       FLAC__ASSERT(decoder->private_->eof_callback);
+
+       if(FLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= FLAC__stream_decoder_get_total_samples(decoder))
+               return false;
+
+       decoder->private_->is_seeking = true;
+
+       /* turn off md5 checking if a seek is attempted */
+       decoder->private_->do_md5_checking = false;
+
+       /* get the file length (currently our algorithm needs to know the length so it's also an error to get FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED) */
+       if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != FLAC__STREAM_DECODER_LENGTH_STATUS_OK) {
+               decoder->private_->is_seeking = false;
+               return false;
+       }
+       /* if we haven't finished processing the metadata yet, do that so we have the STREAMINFO, SEEK_TABLE, and first_frame_offset */
+       if(
+               decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA ||
+               decoder->protected_->state == FLAC__STREAM_DECODER_READ_METADATA
+       ) {
+               if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) {
+                       /* above call sets the state for us */
+                       decoder->private_->is_seeking = false;
+                       return false;
+               }
+               /* check this again in case we didn't know total_samples the first time */
+               if(FLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= FLAC__stream_decoder_get_total_samples(decoder)) {
+                       decoder->private_->is_seeking = false;
+                       return false;
+               }
+       }
+
+       {
+               FLAC__bool ok = seek_to_absolute_sample_(decoder, length, sample);
+               decoder->private_->is_seeking = false;
+               return ok;
+       }
+}
+
 /***********************************************************************
  *
  * Protected class methods
@@ -770,14 +1087,42 @@ unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecod
 void set_defaults_(FLAC__StreamDecoder *decoder)
 {
        decoder->private_->read_callback = 0;
+       decoder->private_->seek_callback = 0;
+       decoder->private_->tell_callback = 0;
+       decoder->private_->length_callback = 0;
+       decoder->private_->eof_callback = 0;
        decoder->private_->write_callback = 0;
        decoder->private_->metadata_callback = 0;
        decoder->private_->error_callback = 0;
        decoder->private_->client_data = 0;
+#ifdef OLD_STAT_WAY
+       decoder->private_->filename = 0;
+#endif
 
        memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter));
        decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] = true;
        decoder->private_->metadata_filter_ids_count = 0;
+
+       decoder->protected_->md5_checking = false;
+}
+
+/*
+ * This will forcibly set stdin to binary mode (for OSes that require it)
+ */
+FILE *get_binary_stdin_()
+{
+       /* if something breaks here it is probably due to the presence or
+        * absence of an underscore before the identifiers 'setmode',
+        * 'fileno', and/or 'O_BINARY'; check your system header files.
+        */
+#if defined _MSC_VER || defined __MINGW32__
+       _setmode(_fileno(stdin), _O_BINARY);
+#elif defined __CYGWIN__ || defined __EMX__
+       /* almost certainly not needed for any modern Cygwin, but let's be safe... */
+       setmode(_fileno(stdin), _O_BINARY);
+#endif
+
+       return stdin;
 }
 
 FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels)
@@ -860,7 +1205,7 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder)
                }
                else {
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                }
                if(x == FLAC__STREAM_SYNC_STRING[i]) {
                        first = true;
@@ -873,14 +1218,14 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder)
                        i = 0;
                        if(id == 3) {
                                if(!skip_id3v2_tag_(decoder))
-                                       return false; /* the read_callback_ sets the state for us */
+                                       return false; /* skip_id3v2_tag_ sets the state for us */
                        }
                        continue;
                }
                if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
                        decoder->private_->header_warmup[0] = (FLAC__byte)x;
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
 
                        /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */
                        /* else we have to check if the second byte is the end of a sync code */
@@ -896,7 +1241,7 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder)
                }
                i = 0;
                if(first) {
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
                        first = false;
                }
        }
@@ -913,21 +1258,23 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
        FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
 
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_IS_LAST_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        is_last = x? true : false;
 
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        if(type == FLAC__METADATA_TYPE_STREAMINFO) {
                if(!read_metadata_streaminfo_(decoder, is_last, length))
                        return false;
 
                decoder->private_->has_stream_info = true;
-               if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO])
+               if(0 == memcmp(decoder->private_->stream_info.data.stream_info.md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
+                       decoder->private_->do_md5_checking = false;
+               if(!decoder->private_->is_seeking && decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] && decoder->private_->metadata_callback)
                        decoder->private_->metadata_callback(decoder, &decoder->private_->stream_info, decoder->private_->client_data);
        }
        else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
@@ -935,7 +1282,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
                        return false;
 
                decoder->private_->has_seek_table = true;
-               if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_SEEKTABLE])
+               if(!decoder->private_->is_seeking && decoder->private_->metadata_filter[FLAC__METADATA_TYPE_SEEKTABLE] && decoder->private_->metadata_callback)
                        decoder->private_->metadata_callback(decoder, &decoder->private_->seek_table, decoder->private_->client_data);
        }
        else {
@@ -949,7 +1296,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
 
                if(type == FLAC__METADATA_TYPE_APPLICATION) {
                        if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
 
                        real_length -= FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
 
@@ -959,14 +1306,14 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
 
                if(skip_it) {
                        if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, real_length, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                }
                else {
                        switch(type) {
                                case FLAC__METADATA_TYPE_PADDING:
                                        /* skip the padding bytes */
                                        if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, real_length, read_callback_, decoder))
-                                               return false; /* the read_callback_ sets the state for us */
+                                               return false; /* read_callback_ sets the state for us */
                                        break;
                                case FLAC__METADATA_TYPE_APPLICATION:
                                        /* remember, we read the ID already */
@@ -976,7 +1323,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
                                                        return false;
                                                }
                                                if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length, read_callback_, decoder))
-                                                       return false; /* the read_callback_ sets the state for us */
+                                                       return false; /* read_callback_ sets the state for us */
                                        }
                                        else
                                                block.data.application.data = 0;
@@ -1000,13 +1347,14 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
                                                        return false;
                                                }
                                                if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length, read_callback_, decoder))
-                                                       return false; /* the read_callback_ sets the state for us */
+                                                       return false; /* read_callback_ sets the state for us */
                                        }
                                        else
                                                block.data.unknown.data = 0;
                                        break;
                        }
-                       decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data);
+                       if(!decoder->private_->is_seeking && decoder->private_->metadata_callback)
+                               decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data);
 
                        /* now we have to free any malloc'ed data in the block */
                        switch(type) {
@@ -1045,8 +1393,12 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
                }
        }
 
-       if(is_last)
+       if(is_last) {
+               /* if this fails, it's OK, it's just a hint for the seek routine */
+               if(!FLAC__stream_decoder_get_decode_position(decoder, &decoder->private_->first_frame_offset))
+                       decoder->private_->first_frame_offset = 0;
                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
+       }
 
        return true;
 }
@@ -1064,60 +1416,60 @@ FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is
 
        bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN;
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, bits, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        decoder->private_->stream_info.data.stream_info.min_blocksize = x;
        used_bits += bits;
 
        bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN;
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        decoder->private_->stream_info.data.stream_info.max_blocksize = x;
        used_bits += bits;
 
        bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN;
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        decoder->private_->stream_info.data.stream_info.min_framesize = x;
        used_bits += bits;
 
        bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN;
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        decoder->private_->stream_info.data.stream_info.max_framesize = x;
        used_bits += bits;
 
        bits = FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN;
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        decoder->private_->stream_info.data.stream_info.sample_rate = x;
        used_bits += bits;
 
        bits = FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN;
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        decoder->private_->stream_info.data.stream_info.channels = x+1;
        used_bits += bits;
 
        bits = FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN;
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        decoder->private_->stream_info.data.stream_info.bits_per_sample = x+1;
        used_bits += bits;
 
        bits = FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN;
        if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &decoder->private_->stream_info.data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        used_bits += bits;
 
        if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, decoder->private_->stream_info.data.stream_info.md5sum, 16, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        used_bits += 16*8;
 
        /* skip the rest of the block */
        FLAC__ASSERT(used_bits % 8 == 0);
        length -= (used_bits / 8);
        if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        return true;
 }
@@ -1142,15 +1494,15 @@ FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_
        }
        for(i = 0; i < decoder->private_->seek_table.data.seek_table.num_points; i++) {
                if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                decoder->private_->seek_table.data.seek_table.points[i].sample_number = xx;
 
                if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                decoder->private_->seek_table.data.seek_table.points[i].stream_offset = xx;
 
                if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                decoder->private_->seek_table.data.seek_table.points[i].frame_samples = x;
        }
        length -= (decoder->private_->seek_table.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH);
@@ -1158,7 +1510,7 @@ FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_
        if(length > 0) {
                /*@@@ do an error_callback() here?  there's an argument for either way */
                if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, length, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
        }
 
        return true;
@@ -1173,14 +1525,14 @@ FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__Stre
        /* read vendor string */
        FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32);
        if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        if(obj->vendor_string.length > 0) {
                if(0 == (obj->vendor_string.entry = (FLAC__byte*)malloc(obj->vendor_string.length+1))) {
                        decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
                        return false;
                }
                if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                obj->vendor_string.entry[obj->vendor_string.length] = '\0';
        }
        else
@@ -1189,7 +1541,7 @@ FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__Stre
        /* read num comments */
        FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32);
        if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->num_comments, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        /* read comments */
        if(obj->num_comments > 0) {
@@ -1200,14 +1552,14 @@ FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__Stre
                for(i = 0; i < obj->num_comments; i++) {
                        FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32);
                        if(!FLAC__bitbuffer_read_raw_uint32_little_endian(decoder->private_->input, &obj->comments[i].length, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        if(obj->comments[i].length > 0) {
                                if(0 == (obj->comments[i].entry = (FLAC__byte*)malloc(obj->comments[i].length+1))) {
                                        decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
                                        return false;
                                }
                                if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length, read_callback_, decoder))
-                                       return false; /* the read_callback_ sets the state for us */
+                                       return false; /* read_callback_ sets the state for us */
                                obj->comments[i].entry[obj->comments[i].length] = '\0';
                        }
                        else
@@ -1231,20 +1583,20 @@ FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMet
 
        FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0);
        if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &obj->lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        obj->is_cd = x? true : false;
 
        if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        obj->num_tracks = x;
 
        if(obj->num_tracks > 0) {
@@ -1255,29 +1607,29 @@ FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMet
                for(i = 0; i < obj->num_tracks; i++) {
                        FLAC__StreamMetadata_CueSheet_Track *track = &obj->tracks[i];
                        if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
 
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        track->number = (FLAC__byte)x;
 
                        FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0);
                        if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
 
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        track->type = x;
 
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        track->pre_emphasis = x;
 
                        if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
 
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        track->num_indices = (FLAC__byte)x;
 
                        if(track->num_indices > 0) {
@@ -1288,14 +1640,14 @@ FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMet
                                for(j = 0; j < track->num_indices; j++) {
                                        FLAC__StreamMetadata_CueSheet_Index *index = &track->indices[j];
                                        if(!FLAC__bitbuffer_read_raw_uint64(decoder->private_->input, &index->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN, read_callback_, decoder))
-                                               return false; /* the read_callback_ sets the state for us */
+                                               return false; /* read_callback_ sets the state for us */
 
                                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN, read_callback_, decoder))
-                                               return false; /* the read_callback_ sets the state for us */
+                                               return false; /* read_callback_ sets the state for us */
                                        index->number = (FLAC__byte)x;
 
                                        if(!FLAC__bitbuffer_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN, read_callback_, decoder))
-                                               return false; /* the read_callback_ sets the state for us */
+                                               return false; /* read_callback_ sets the state for us */
                                }
                        }
                }
@@ -1311,18 +1663,18 @@ FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder)
 
        /* skip the version and flags bytes */
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 24, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        /* get the size (in bytes) to skip */
        skip = 0;
        for(i = 0; i < 4; i++) {
                if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                skip <<= 7;
                skip |= (x & 0x7f);
        }
        /* skip the rest of the tag */
        if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, 0, skip, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        return true;
 }
 
@@ -1333,8 +1685,8 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder)
 
        /* If we know the total number of samples in the stream, stop if we've read that many. */
        /* This will stop us, for example, from wasting time trying to sync on an ID3V1 tag. */
-       if(decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.total_samples) {
-               if(decoder->private_->samples_decoded >= decoder->private_->stream_info.data.stream_info.total_samples) {
+       if(FLAC__stream_decoder_get_total_samples(decoder) > 0) {
+               if(decoder->private_->samples_decoded >= FLAC__stream_decoder_get_total_samples(decoder)) {
                        decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM;
                        return true;
                }
@@ -1343,7 +1695,7 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder)
        /* make sure we're byte aligned */
        if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) {
                if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
        }
 
        while(1) {
@@ -1353,12 +1705,12 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder)
                }
                else {
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                }
                if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
                        decoder->private_->header_warmup[0] = (FLAC__byte)x;
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
 
                        /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */
                        /* else we have to check if the second byte is the end of a sync code */
@@ -1373,7 +1725,7 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder)
                        }
                }
                if(first) {
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
                        first = false;
                }
        }
@@ -1446,7 +1798,7 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL
         */
        frame_crc = FLAC__bitbuffer_get_read_crc16(decoder->private_->input);
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        if(frame_crc == (FLAC__uint16)x) {
                if(do_full_decode) {
                        /* Undo any special channel coding */
@@ -1486,7 +1838,7 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL
        }
        else {
                /* Bad frame, emit error and zero the output signal */
-               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, decoder->private_->client_data);
+               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH);
                if(do_full_decode) {
                        for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) {
                                memset(decoder->private_->output[channel], 0, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize);
@@ -1508,7 +1860,7 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL
 
        /* write it */
        if(do_full_decode) {
-               if(decoder->private_->write_callback(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output, decoder->private_->client_data) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE)
+               if(write_audio_frame_to_client_(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE)
                        return false;
        }
 
@@ -1552,12 +1904,12 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
         */
        for(i = 0; i < 2; i++) {
                if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
                        /* if we get here it means our original sync was erroneous since the sync code cannot appear in the header */
                        decoder->private_->lookahead = (FLAC__byte)x;
                        decoder->private_->cached = true;
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
                        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                        return true;
                }
@@ -1641,7 +1993,7 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
                        sample_rate_hint = x;
                        break;
                case 15:
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
                        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                        return true;
                default:
@@ -1703,7 +2055,7 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
        }
 
        if(raw_header[3] & 0x01) { /* this should be a zero padding bit */
-               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data);
+               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                return true;
        }
@@ -1723,11 +2075,11 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
        if(is_known_variable_blocksize_stream) {
                if(blocksize_hint) {
                        if(!FLAC__bitbuffer_read_utf8_uint64(decoder->private_->input, &xx, read_callback_, decoder, raw_header, &raw_header_len))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        if(xx == FLAC__U64L(0xffffffffffffffff)) { /* i.e. non-UTF8 code... */
                                decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
                                decoder->private_->cached = true;
-                               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data);
+                               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
                                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                                return true;
                        }
@@ -1739,11 +2091,11 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
        }
        else {
                if(!FLAC__bitbuffer_read_utf8_uint32(decoder->private_->input, &x, read_callback_, decoder, raw_header, &raw_header_len))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                if(x == 0xffffffff) { /* i.e. non-UTF8 code... */
                        decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
                        decoder->private_->cached = true;
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
                        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                        return true;
                }
@@ -1768,12 +2120,12 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
 
        if(blocksize_hint) {
                if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                raw_header[raw_header_len++] = (FLAC__byte)x;
                if(blocksize_hint == 7) {
                        FLAC__uint32 _x;
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        raw_header[raw_header_len++] = (FLAC__byte)_x;
                        x = (x << 8) | _x;
                }
@@ -1782,12 +2134,12 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
 
        if(sample_rate_hint) {
                if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                raw_header[raw_header_len++] = (FLAC__byte)x;
                if(sample_rate_hint != 12) {
                        FLAC__uint32 _x;
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &_x, 8, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        raw_header[raw_header_len++] = (FLAC__byte)_x;
                        x = (x << 8) | _x;
                }
@@ -1801,17 +2153,17 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
 
        /* read the CRC-8 byte */
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        crc8 = (FLAC__byte)x;
 
        if(FLAC__crc8(raw_header, raw_header_len) != crc8) {
-               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data);
+               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                return true;
        }
 
        if(is_unparseable) {
-               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM, decoder->private_->client_data);
+               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                return true;
        }
@@ -1826,7 +2178,7 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
        unsigned i;
 
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &x, 8, read_callback_, decoder)) /* MAGIC NUMBER */
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        wasted_bits = (x & 1);
        x &= 0xfe;
@@ -1834,7 +2186,7 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
        if(wasted_bits) {
                unsigned u;
                if(!FLAC__bitbuffer_read_unary_unsigned(decoder->private_->input, &u, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                decoder->private_->frame.subframes[channel].wasted_bits = u+1;
                bps -= decoder->private_->frame.subframes[channel].wasted_bits;
        }
@@ -1845,7 +2197,7 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
         * Lots of magic numbers here
         */
        if(x & 0x80) {
-               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data);
+               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                return true;
        }
@@ -1858,7 +2210,7 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
                        return false;
        }
        else if(x < 16) {
-               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM, decoder->private_->client_data);
+               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                return true;
        }
@@ -1869,7 +2221,7 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign
                        return true;
        }
        else if(x < 64) {
-               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM, decoder->private_->client_data);
+               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                return true;
        }
@@ -1899,7 +2251,7 @@ FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channe
        decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT;
 
        if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
 
        subframe->value = x;
 
@@ -1927,23 +2279,23 @@ FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel,
        /* read warm-up samples */
        for(u = 0; u < order; u++) {
                if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                subframe->warmup[u] = i32;
        }
 
        /* read entropy coding method info */
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32;
        switch(subframe->entropy_coding_method.type) {
                case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        subframe->entropy_coding_method.data.partitioned_rice.order = u32;
                        subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel];
                        break;
                default:
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
                        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                        return true;
        }
@@ -1982,15 +2334,15 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un
        /* read warm-up samples */
        for(u = 0; u < order; u++) {
                if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, bps, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                subframe->warmup[u] = i32;
        }
 
        /* read qlp coeff precision */
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        if(u32 == (1u << FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1) {
-               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data);
+               send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
                decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                return true;
        }
@@ -1998,29 +2350,29 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un
 
        /* read qlp shift */
        if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        subframe->quantization_level = i32;
 
        /* read quantized lp coefficiencts */
        for(u = 0; u < order; u++) {
                if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i32, subframe->qlp_coeff_precision, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                subframe->qlp_coeff[u] = i32;
        }
 
        /* read entropy coding method info */
        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN, read_callback_, decoder))
-               return false; /* the read_callback_ sets the state for us */
+               return false; /* read_callback_ sets the state for us */
        subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32;
        switch(subframe->entropy_coding_method.type) {
                case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        subframe->entropy_coding_method.data.partitioned_rice.order = u32;
                        subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel];
                        break;
                default:
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
                        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                        return true;
        }
@@ -2066,7 +2418,7 @@ FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channe
 
        for(i = 0; i < decoder->private_->frame.header.blocksize; i++) {
                if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &x, bps, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                residual[i] = x;
        }
 
@@ -2088,14 +2440,14 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigne
        /* sanity checks */
        if(partition_order == 0) {
                if(decoder->private_->frame.header.blocksize < predictor_order) {
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
                        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                        return true;
                }
        }
        else {
                if(partition_samples < predictor_order) {
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
                        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                        return true;
                }
@@ -2109,21 +2461,21 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigne
        sample = 0;
        for(partition = 0; partition < partitions; partition++) {
                if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN, read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                partitioned_rice_contents->parameters[partition] = rice_parameter;
                if(rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) {
                        u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order;
                        if(!FLAC__bitbuffer_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        sample += u;
                }
                else {
                        if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN, read_callback_, decoder))
-                               return false; /* the read_callback_ sets the state for us */
+                               return false; /* read_callback_ sets the state for us */
                        partitioned_rice_contents->raw_bits[partition] = rice_parameter;
                        for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) {
                                if(!FLAC__bitbuffer_read_raw_int32(decoder->private_->input, &i, rice_parameter, read_callback_, decoder))
-                                       return false; /* the read_callback_ sets the state for us */
+                                       return false; /* read_callback_ sets the state for us */
                                residual[sample] = i;
                        }
                }
@@ -2137,9 +2489,9 @@ FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder)
        if(!FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input)) {
                FLAC__uint32 zero = 0;
                if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &zero, FLAC__bitbuffer_bits_left_for_byte_alignment(decoder->private_->input), read_callback_, decoder))
-                       return false; /* the read_callback_ sets the state for us */
+                       return false; /* read_callback_ sets the state for us */
                if(zero != 0) {
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, decoder->private_->client_data);
+                       send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
                        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
                }
        }
@@ -2149,12 +2501,412 @@ FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder)
 FLAC__bool read_callback_(FLAC__byte buffer[], unsigned *bytes, void *client_data)
 {
        FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder *)client_data;
-       FLAC__StreamDecoderReadStatus status;
 
-       status = decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data);
-       if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM)
+       if(decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data)) {
+               *bytes = 0;
                decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM;
-       else if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT)
+               return false;
+       }
+       else if(*bytes > 0) {
+               /* While seeking, it is possible for our seek to land in the
+                * middle of audio data that looks exactly like a frame header
+                * from a future version of an encoder.  When that happens, our
+                * error callback will get an
+                * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM and increment its
+                * unparseable_frame_count.  But there is a remote possibility
+                * that it is properly synced at such a "future-codec frame",
+                * so to make sure, we wait to see many "unparseable" errors in
+                * a row before bailing out.
+                */
+               if(decoder->private_->is_seeking && decoder->private_->unparseable_frame_count > 20) {
+                       decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
+                       return false;
+               }
+               else {
+                       const FLAC__StreamDecoderReadStatus status = decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data);
+                       if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) {
+                               decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
+                               return false;
+                       }
+                       else if(*bytes == 0) {
+                               if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM || (decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data))) {
+                                       decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM;
+                                       return false;
+                               }
+                               else
+                                       return true;
+                       }
+                       else
+                               return true;
+               }
+       }
+       else {
+               /* abort to avoid a deadlock */
                decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
-       return status == FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+               return false;
+       }
+}
+
+FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
+{
+       if(decoder->private_->is_seeking) {
+               FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
+               FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
+               FLAC__uint64 target_sample = decoder->private_->target_sample;
+
+               FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
+
+               decoder->private_->last_frame = *frame; /* save the frame */
+               if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
+                       unsigned delta = (unsigned)(target_sample - this_frame_sample);
+                       /* kick out of seek mode */
+                       decoder->private_->is_seeking = false;
+                       /* shift out the samples before target_sample */
+                       if(delta > 0) {
+                               unsigned channel;
+                               const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
+                               for(channel = 0; channel < frame->header.channels; channel++)
+                                       newbuffer[channel] = buffer[channel] + delta;
+                               decoder->private_->last_frame.header.blocksize -= delta;
+                               decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
+                               /* write the relevant samples */
+                               return decoder->private_->write_callback(decoder, &decoder->private_->last_frame, newbuffer, decoder->private_->client_data);
+                       }
+                       else {
+                               /* write the relevant samples */
+                               return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data);
+                       }
+               }
+               else {
+                       return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+               }
+       }
+       else {
+               /*
+                * If we never got STREAMINFO, turn off MD5 checking to save
+                * cycles since we don't have a sum to compare to anyway
+                */
+               if(!decoder->private_->has_stream_info)
+                       decoder->private_->do_md5_checking = false;
+               if(decoder->private_->do_md5_checking) {
+                       if(!FLAC__MD5Accumulate(&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 decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data);
+       }
+}
+
+void send_error_to_client_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status)
+{
+       if(!decoder->private_->is_seeking)
+               decoder->private_->error_callback(decoder, status, decoder->private_->client_data);
+       else if(status == FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM)
+               decoder->private_->unparseable_frame_count++;
+}
+
+FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
+{
+       FLAC__uint64 first_frame_offset = decoder->private_->first_frame_offset, lower_bound, upper_bound;
+       FLAC__int64 pos = -1, last_pos = -1;
+       int i, lower_seek_point = -1, upper_seek_point = -1;
+       unsigned approx_bytes_per_frame;
+       FLAC__uint64 last_frame_sample = FLAC__U64L(0xffffffffffffffff);
+       FLAC__bool needs_seek;
+       const FLAC__uint64 total_samples = FLAC__stream_decoder_get_total_samples(decoder);
+       const unsigned min_blocksize = decoder->private_->stream_info.data.stream_info.min_blocksize;
+       const unsigned max_blocksize = decoder->private_->stream_info.data.stream_info.max_blocksize;
+       const unsigned max_framesize = decoder->private_->stream_info.data.stream_info.max_framesize;
+       const unsigned channels = FLAC__stream_decoder_get_channels(decoder);
+       const unsigned bps = FLAC__stream_decoder_get_bits_per_sample(decoder);
+       const FLAC__StreamMetadata_SeekTable *seek_table = decoder->private_->has_seek_table? &decoder->private_->seek_table.data.seek_table : 0;
+
+       /* we are just guessing here, but we want to guess high, not low */
+       if(max_framesize > 0)
+               approx_bytes_per_frame = max_framesize;
+
+       /*
+        * Check if it's a known fixed-blocksize stream.  Note that though
+        * the spec doesn't allow zeroes in the STREAMINFO block, we may
+        * never get a STREAMINFO block when decoding so the value of
+        * min_blocksize might be zero.
+        */
+       else if(min_blocksize == max_blocksize && min_blocksize > 0) {
+               /* note there are no () around 'bps/8' to keep precision up since it's an integer calulation */
+               approx_bytes_per_frame = min_blocksize * channels * bps/8 + 64;
+       }
+       else
+               approx_bytes_per_frame = 4608 * channels * bps/8 + 64;
+
+       /*
+        * First, we set an upper and lower bound on where in the
+        * stream we will search.  For now we assume the worst case
+        * scenario, which is our best guess at the beginning of
+        * the first and last frames.
+        */
+       lower_bound = first_frame_offset;
+
+       /* calc the upper_bound, beyond which we never want to seek */
+       if(max_framesize > 0)
+               upper_bound = stream_length - (max_framesize + 128 + 2); /* 128 for a possible ID3V1 tag, 2 for indexing differences */
+       else
+               upper_bound = stream_length - ((channels * bps * FLAC__MAX_BLOCK_SIZE) / 8 + 128 + 2);
+
+       /*
+        * Now we refine the bounds if we have a seektable with
+        * suitable points.  Note that according to the spec they
+        * must be ordered by ascending sample number.
+        */
+       if(seek_table) {
+               /* find the closest seek point <= target_sample, if it exists */
+               for(i = (int)seek_table->num_points - 1; i >= 0; i--) {
+                       if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && seek_table->points[i].sample_number <= target_sample)
+                               break;
+               }
+               if(i >= 0) { /* i.e. we found a suitable seek point... */
+                       lower_bound = first_frame_offset + seek_table->points[i].stream_offset;
+                       lower_seek_point = i;
+               }
+
+               /* find the closest seek point > target_sample, if it exists */
+               for(i = 0; i < (int)seek_table->num_points; i++) {
+                       if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && seek_table->points[i].sample_number > target_sample)
+                               break;
+               }
+               if(i < (int)seek_table->num_points) { /* i.e. we found a suitable seek point... */
+                       upper_bound = first_frame_offset + seek_table->points[i].stream_offset;
+                       upper_seek_point = i;
+               }
+       }
+
+       /*
+        * Now guess at where within those bounds our target
+        * sample will be.
+        */
+       if(seek_table && lower_seek_point >= 0) {
+               /* first see if our sample is within a few frames of the lower seekpoint */
+               if(seek_table->points[lower_seek_point].sample_number <= target_sample && target_sample < seek_table->points[lower_seek_point].sample_number + (seek_table->points[lower_seek_point].frame_samples * 4)) {
+                       pos = (FLAC__int64)lower_bound;
+               }
+               else if(upper_seek_point >= 0) {
+                       const FLAC__uint64 target_offset = target_sample - seek_table->points[lower_seek_point].sample_number;
+                       const FLAC__uint64 range_samples = seek_table->points[upper_seek_point].sample_number - seek_table->points[lower_seek_point].sample_number;
+                       const FLAC__uint64 range_bytes = (upper_bound>lower_bound? upper_bound - lower_bound - 1 : 0);
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+#if defined _MSC_VER || defined __MINGW32__
+                       /* with MSVC you have to spoon feed it the casting */
+                       pos = (FLAC__int64)lower_bound + (FLAC__int64)(((FLAC__double)(FLAC__int64)target_offset / (FLAC__double)(FLAC__int64)range_samples) * (FLAC__double)(FLAC__int64)(range_bytes-1)) - approx_bytes_per_frame;
+#else
+                       pos = (FLAC__int64)lower_bound + (FLAC__int64)(((FLAC__double)target_offset / (FLAC__double)range_samples) * (FLAC__double)range_bytes) - approx_bytes_per_frame;
+#endif
+#else
+                       /* a little less accurate: */
+                       if (range_bytes <= 0xffffffff)
+                               pos = (FLAC__int64)lower_bound + (FLAC__int64)((target_offset * range_bytes) / range_samples) - approx_bytes_per_frame;
+                       else /* @@@ WATCHOUT, ~2TB limit */
+                               pos = (FLAC__int64)lower_bound + (FLAC__int64)(((target_offset>>8) * (range_bytes>>8)) / (range_samples>>16)) - approx_bytes_per_frame;
+#endif
+               }
+       }
+
+       /*
+        * If there's no seek table, we need to use the metadata (if we
+        * have it) and the filelength to estimate the position of the
+        * frame with the correct sample.
+        */
+       if(pos < 0 && total_samples > 0) {
+               /*
+                * For max accuracy we should be using
+                * (stream_length-first_frame_offset-1) in the divisor, but the
+                * difference is trivial and (stream_length-first_frame_offset)
+                * has no chance of underflow.
+                */
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+#if defined _MSC_VER || defined __MINGW32__
+               /* with VC++ you have to spoon feed it the casting */
+               pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((FLAC__double)(FLAC__int64)target_sample / (FLAC__double)(FLAC__int64)total_samples) * (FLAC__double)(FLAC__int64)(stream_length-first_frame_offset)) - approx_bytes_per_frame;
+#else
+               pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((FLAC__double)target_sample / (FLAC__double)total_samples) * (FLAC__double)(stream_length-first_frame_offset)) - approx_bytes_per_frame;
+#endif
+#else
+               /* a little less accurate: */
+               if (stream_length < 0xffffffff)
+                       pos = (FLAC__int64)first_frame_offset + (FLAC__int64)((target_sample * (stream_length-first_frame_offset)) / total_samples) - approx_bytes_per_frame;
+               else /* @@@ WATCHOUT, ~2TB limit */
+                       pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((target_sample>>8) * ((stream_length-first_frame_offset)>>8)) / (total_samples>>16)) - approx_bytes_per_frame;
+#endif
+       }
+
+       /*
+        * If there's no seek table and total_samples is unknown, we
+        * don't even bother trying to figure out a target, we just use
+        * our current position.
+        */
+       if(pos < 0) {
+               FLAC__uint64 upos;
+               if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__STREAM_DECODER_TELL_STATUS_OK) {
+                       decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
+                       return false;
+               }
+               pos = (FLAC__int64)upos;
+               needs_seek = false;
+       }
+       else
+               needs_seek = true;
+
+       /* clip the position to the bounds, lower bound takes precedence */
+       if(pos >= (FLAC__int64)upper_bound) {
+               pos = (FLAC__int64)upper_bound-1;
+               needs_seek = true;
+       }
+       if(pos < (FLAC__int64)lower_bound) {
+               pos = (FLAC__int64)lower_bound;
+               needs_seek = true;
+       }
+
+       decoder->private_->target_sample = target_sample;
+       while(1) {
+               if(needs_seek) {
+                       if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) {
+                               decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
+                               return false;
+                       }
+                       if(!FLAC__stream_decoder_flush(decoder)) {
+                               /* above call sets the state for us */
+                               return false;
+                       }
+               }
+               /* Now we need to get a frame.  First we need to reset our
+                * unparseable_frame_count; if we get too many unparseable
+                * frames in a row, the read callback will return
+                * FLAC__STREAM_DECODER_READ_STATUS_ABORT, causing
+                * FLAC__stream_decoder_process_single() to return false.
+                */
+               decoder->private_->unparseable_frame_count = 0;
+               if(!FLAC__stream_decoder_process_single(decoder)) {
+                       decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
+                       return false;
+               }
+               /* our write callback will change the state when it gets to the target frame */
+               /* actually, we could have got_a_frame if our decoder is at FLAC__STREAM_DECODER_END_OF_STREAM so we need to check for that also */
+#if 0
+               /*@@@@@@ used to be the following; not clear if the check for end of stream is needed anymore */
+               if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING && decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM)
+                       break;
+#endif
+               if(!decoder->private_->is_seeking) {
+                       break;
+               }
+               else { /* we need to narrow the search */
+                       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 == last_frame_sample && pos < last_pos) {
+                               /* our last move backwards wasn't big enough, double it */
+                               pos -= (last_pos - pos);
+                               needs_seek = true;
+                       }
+                       else {
+                               if(target_sample < this_frame_sample) {
+                                       last_pos = pos;
+                                       approx_bytes_per_frame = decoder->private_->last_frame.header.blocksize * channels * bps/8 + 64;
+                                       pos -= approx_bytes_per_frame;
+                                       needs_seek = true;
+                               }
+                               else { /* target_sample >= this_frame_sample + this frame's blocksize */
+                                       FLAC__uint64 upos;
+                                       if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__STREAM_DECODER_TELL_STATUS_OK) {
+                                               decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
+                                               return false;
+                                       }
+                                       last_pos = pos;
+                                       pos = (FLAC__int64)upos;
+                                       pos -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder);
+                                       needs_seek = false;
+                                       /*
+                                        * if we haven't hit the target frame yet and our position hasn't changed,
+                                        * it means we're at the end of the stream and the seek target does not exist.
+                                        */
+                                       if(last_pos == pos) {
+                                               decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
+                                               return false;
+                                       }
+                               }
+                       }
+                       if(pos < (FLAC__int64)lower_bound)
+                               pos = (FLAC__int64)lower_bound;
+                       last_frame_sample = this_frame_sample;
+               }
+       }
+
+       return true;
+}
+
+FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+       (void)client_data;
+
+       if(*bytes > 0) {
+               *bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, decoder->private_->file);
+               if(ferror(decoder->private_->file))
+                       return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+               else if(*bytes == 0)
+                       return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+               else
+                       return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+       }
+       else
+               return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
+}
+
+FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+       (void)client_data;
+
+       if(decoder->private_->file == stdin)
+               return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+       else if(fseeko(decoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+       else
+               return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+       off_t pos;
+       (void)client_data;
+
+       if(decoder->private_->file == stdin) /*@@@@@@ may work for stdin */
+               return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
+       else if((pos = ftello(decoder->private_->file)) < 0)
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+       else {
+               *absolute_byte_offset = (FLAC__uint64)pos;
+               return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+       }
+}
+
+FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
+{
+       struct stat filestats;
+       (void)client_data;
+
+       if(decoder->private_->file == stdin)
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+#ifdef OLD_STAT_WAY
+       else if(0 == decoder->private_->filename || fstat(fileno(decoder->private_->file), &filestats) != 0)
+#endif
+       else if(fstat(fileno(decoder->private_->file), &filestats) != 0)
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+       else {
+               *stream_length = (FLAC__uint64)filestats.st_size;
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+       }
+}
+
+FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data)
+{
+       (void)client_data;
+
+       if(decoder->private_->file == stdin) /*@@@@@@ feof() may work for stdin */
+               return false;
+       return feof(decoder->private_->file)? true : false;
 }
index 6ecb872..be11e5e 100644 (file)
 #  include <config.h>
 #endif
 
+#if defined _MSC_VER || defined __MINGW32__
+#include <io.h> /* for _setmode() */
+#include <fcntl.h> /* for _O_BINARY */
+#endif
+#if defined __CYGWIN__ || defined __EMX__
+#include <io.h> /* for setmode(), O_BINARY */
+#include <fcntl.h> /* for _O_BINARY */
+#endif
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h> /* for malloc() */
 #include <string.h> /* for memcpy() */
+#include <sys/types.h> /* for off_t */
+#if defined _MSC_VER || defined __MINGW32__
+/*@@@ [2G limit] hacks for MSVC6 */
+#define fseeko fseek
+#define ftello ftell
+#endif
 #include "FLAC/assert.h"
 #include "FLAC/stream_decoder.h"
 #include "protected/stream_encoder.h"
@@ -93,6 +107,8 @@ static void set_defaults_(FLAC__StreamEncoder *encoder);
 static void free_(FLAC__StreamEncoder *encoder);
 static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size);
 static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples);
+static FLAC__StreamEncoderWriteStatus write_frame_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples);
+static void update_metadata_(const FLAC__StreamEncoder *encoder);
 static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
 static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame);
 
@@ -297,31 +313,15 @@ static void append_to_verify_fifo_interleaved_(
        unsigned wide_samples
 );
 
-static FLAC__StreamDecoderReadStatus verify_read_callback_(
-       const FLAC__StreamDecoder *decoder,
-       FLAC__byte buffer[],
-       unsigned *bytes,
-       void *client_data
-);
+static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+static void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
 
-static FLAC__StreamDecoderWriteStatus verify_write_callback_(
-       const FLAC__StreamDecoder *decoder,
-       const FLAC__Frame *frame,
-       const FLAC__int32 * const buffer[],
-       void *client_data
-);
-
-static void verify_metadata_callback_(
-       const FLAC__StreamDecoder *decoder,
-       const FLAC__StreamMetadata *metadata,
-       void *client_data
-);
-
-static void verify_error_callback_(
-       const FLAC__StreamDecoder *decoder,
-       FLAC__StreamDecoderErrorStatus status,
-       void *client_data
-);
+static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
+static FILE *get_binary_stdout_();
 
 #ifdef WINDOW_DEBUG_OUTPUT
 static const char * const winstr[] = {
@@ -382,7 +382,8 @@ typedef struct FLAC__StreamEncoderPrivate {
        unsigned loose_mid_side_stereo_frames;            /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
        unsigned loose_mid_side_stereo_frame_count;       /* number of frames using the current channel assignment */
        FLAC__ChannelAssignment last_channel_assignment;
-       FLAC__StreamMetadata metadata;
+       FLAC__StreamMetadata streaminfo;                  /* scratchpad for STREAMINFO as it is built */
+       FLAC__StreamMetadata_SeekTable *seek_table;       /* pointer into encoder->protected_->metadata_ where the seek table is */
        unsigned current_sample_number;
        unsigned current_frame_number;
        struct FLAC__MD5Context md5context;
@@ -405,9 +406,18 @@ typedef struct FLAC__StreamEncoderPrivate {
        FLAC__bool disable_constant_subframes;
        FLAC__bool disable_fixed_subframes;
        FLAC__bool disable_verbatim_subframes;
+       FLAC__StreamEncoderSeekCallback seek_callback;
+       FLAC__StreamEncoderTellCallback tell_callback;
        FLAC__StreamEncoderWriteCallback write_callback;
        FLAC__StreamEncoderMetadataCallback metadata_callback;
+       FLAC__StreamEncoderProgressCallback progress_callback;
        void *client_data;
+       unsigned first_seekpoint_to_check;
+       FILE *file;                            /* only used when encoding to a file */
+       FLAC__uint64 bytes_written;
+       FLAC__uint64 samples_written;
+       unsigned frames_written;
+       unsigned total_frames_estimate;
        /* unaligned (original) pointers to allocated data */
        FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
        FLAC__int32 *integer_signal_mid_side_unaligned[2];
@@ -459,27 +469,32 @@ typedef struct FLAC__StreamEncoderPrivate {
 
 FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
        "FLAC__STREAM_ENCODER_OK",
+       "FLAC__STREAM_ENCODER_UNINITIALIZED",
        "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
        "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
-       "FLAC__STREAM_ENCODER_INVALID_CALLBACK",
-       "FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS",
-       "FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE",
-       "FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE",
-       "FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE",
-       "FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER",
-       "FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION",
-       "FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH",
-       "FLAC__STREAM_ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH",
-       "FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE",
-       "FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
-       "FLAC__STREAM_ENCODER_NOT_STREAMABLE",
+       "FLAC__STREAM_ENCODER_CLIENT_ERROR",
+       "FLAC__STREAM_ENCODER_IO_ERROR",
        "FLAC__STREAM_ENCODER_FRAMING_ERROR",
-       "FLAC__STREAM_ENCODER_INVALID_METADATA",
-       "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING",
-       "FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING",
-       "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
-       "FLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
-       "FLAC__STREAM_ENCODER_UNINITIALIZED"
+       "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR"
+};
+
+FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = {
+       "FLAC__STREAM_ENCODER_INIT_STATUS_OK",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_MID_SIDE_CHANNELS_MISMATCH",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_MID_SIDE_SAMPLE_SIZE_MISMATCH",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_ILLEGAL_MID_SIDE_FORCE",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA",
+       "FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED"
 };
 
 FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
@@ -487,6 +502,18 @@ FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
        "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
 };
 
+FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[] = {
+       "FLAC__STREAM_ENCODER_SEEK_STATUS_OK",
+       "FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR",
+       "FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED"
+};
+
+FLAC_API const char * const FLAC__StreamEncoderTellStatusString[] = {
+       "FLAC__STREAM_ENCODER_TELL_STATUS_OK",
+       "FLAC__STREAM_ENCODER_TELL_STATUS_ERROR",
+       "FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED"
+};
+
 /***********************************************************************
  *
  * Class constructor/destructor
@@ -525,6 +552,8 @@ FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new()
                return 0;
        }
 
+       encoder->private_->file = 0;
+
        set_defaults_(encoder);
 
        encoder->private_->is_being_deleted = false;
@@ -601,7 +630,7 @@ FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
  *
  ***********************************************************************/
 
-FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
+FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback write_callback, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderTellCallback tell_callback, FLAC__StreamEncoderMetadataCallback metadata_callback, void *client_data)
 {
        unsigned i;
        FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment;
@@ -609,39 +638,37 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
        FLAC__ASSERT(0 != encoder);
 
        if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
 
-       encoder->protected_->state = FLAC__STREAM_ENCODER_OK;
-
-       if(0 == encoder->private_->write_callback || 0 == encoder->private_->metadata_callback)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_CALLBACK;
+       if(0 == write_callback || (seek_callback && 0 == tell_callback))
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
 
        if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS;
 
        if(encoder->protected_->do_mid_side_stereo && encoder->protected_->channels != 2)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_MID_SIDE_CHANNELS_MISMATCH;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_MID_SIDE_CHANNELS_MISMATCH;
 
        if(encoder->protected_->loose_mid_side_stereo && !encoder->protected_->do_mid_side_stereo)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_ILLEGAL_MID_SIDE_FORCE;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ILLEGAL_MID_SIDE_FORCE;
 
        if(encoder->protected_->bits_per_sample >= 32)
-               encoder->protected_->do_mid_side_stereo = false; /* since we do 32-bit math, the side channel would have 33 bps and overflow */
+               encoder->protected_->do_mid_side_stereo = false; /* since we currenty do 32-bit math, the side channel would have 33 bps and overflow */
 
        if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE;
 
        if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_SAMPLE_RATE;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE;
 
        if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_BLOCK_SIZE;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE;
 
        if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_MAX_LPC_ORDER;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER;
 
        if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
 
        if(encoder->protected_->qlp_coeff_precision == 0) {
                if(encoder->protected_->bits_per_sample < 16) {
@@ -676,7 +703,7 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
                FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
        }
        else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_QLP_COEFF_PRECISION;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION;
 
        if(encoder->protected_->streamable_subset) {
                if(
@@ -693,7 +720,7 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
                        encoder->protected_->blocksize != 8192 &&
                        encoder->protected_->blocksize != 16384
                )
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
                if(
                        encoder->protected_->sample_rate != 8000 &&
                        encoder->protected_->sample_rate != 16000 &&
@@ -704,7 +731,7 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
                        encoder->protected_->sample_rate != 48000 &&
                        encoder->protected_->sample_rate != 96000
                )
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
                if(
                        encoder->protected_->bits_per_sample != 8 &&
                        encoder->protected_->bits_per_sample != 12 &&
@@ -712,9 +739,9 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
                        encoder->protected_->bits_per_sample != 20 &&
                        encoder->protected_->bits_per_sample != 24
                )
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
                if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_NOT_STREAMABLE;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
        }
 
        if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
@@ -724,27 +751,27 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
 
        /* validate metadata */
        if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
        metadata_has_seektable = false;
        metadata_has_vorbis_comment = false;
        for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
                if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
                else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
                        if(metadata_has_seektable) /* only one is allowed */
-                               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+                               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
                        metadata_has_seektable = true;
                        if(!FLAC__format_seektable_is_legal(&encoder->protected_->metadata[i]->data.seek_table))
-                               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+                               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
                }
                else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
                        if(metadata_has_vorbis_comment) /* only one is allowed */
-                               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+                               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
                        metadata_has_vorbis_comment = true;
                }
                else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_CUESHEET) {
                        if(!FLAC__format_cuesheet_is_legal(&encoder->protected_->metadata[i]->data.cue_sheet, encoder->protected_->metadata[i]->data.cue_sheet.is_cd, /*violation=*/0))
-                               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+                               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
                }
        }
 
@@ -861,13 +888,24 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
        /* we require precompute_partition_sums if do_escape_coding because of their intertwined nature */
        encoder->private_->precompute_partition_sums = (encoder->protected_->max_residual_partition_order > encoder->protected_->min_residual_partition_order) || encoder->protected_->do_escape_coding;
 
+       /* set state to OK; from here on, errors are fatal and we'll override the state then */
+       encoder->protected_->state = FLAC__STREAM_ENCODER_OK;
+
+       encoder->private_->write_callback = write_callback;
+       encoder->private_->seek_callback = seek_callback;
+       encoder->private_->tell_callback = tell_callback;
+       encoder->private_->metadata_callback = metadata_callback;
+       encoder->private_->client_data = client_data;
+
        if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
                /* the above function sets the state for us in case of an error */
-               return encoder->protected_->state;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
        }
 
-       if(!FLAC__bitbuffer_init(encoder->private_->frame))
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+       if(!FLAC__bitbuffer_init(encoder->private_->frame)) {
+               encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
 
        /*
         * Set up the verify stuff if necessary
@@ -879,8 +917,10 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
                 */
                encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize;
                for(i = 0; i < encoder->protected_->channels; i++) {
-                       if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size)))
-                               return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+                       if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size))) {
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+                               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+                       }
                }
                encoder->private_->verify.input_fifo.tail = 0;
 
@@ -888,16 +928,15 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
                 * Now set up a stream decoder for verification
                 */
                encoder->private_->verify.decoder = FLAC__stream_decoder_new();
-               if(0 == encoder->private_->verify.decoder)
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
+               if(0 == encoder->private_->verify.decoder) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+               }
 
-               FLAC__stream_decoder_set_read_callback(encoder->private_->verify.decoder, verify_read_callback_);
-               FLAC__stream_decoder_set_write_callback(encoder->private_->verify.decoder, verify_write_callback_);
-               FLAC__stream_decoder_set_metadata_callback(encoder->private_->verify.decoder, verify_metadata_callback_);
-               FLAC__stream_decoder_set_error_callback(encoder->private_->verify.decoder, verify_error_callback_);
-               FLAC__stream_decoder_set_client_data(encoder->private_->verify.decoder, encoder);
-               if(FLAC__stream_decoder_init(encoder->private_->verify.decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
+               if(FLAC__stream_decoder_init_stream(encoder->private_->verify.decoder, verify_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, verify_write_callback_, verify_metadata_callback_, verify_error_callback_, /*client_data=*/encoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+               }
        }
        encoder->private_->verify.error_stats.absolute_sample = 0;
        encoder->private_->verify.error_stats.frame_number = 0;
@@ -907,15 +946,27 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
        encoder->private_->verify.error_stats.got = 0;
 
        /*
+        * These must be done before we write any metadata, because that
+        * calls the write_callback, which uses these values.
+        */
+       encoder->private_->first_seekpoint_to_check = 0;
+       encoder->private_->samples_written = 0;
+       encoder->protected_->streaminfo_offset = 0;
+       encoder->protected_->seektable_offset = 0;
+       encoder->protected_->audio_offset = 0;
+
+       /*
         * write the stream header
         */
        if(encoder->protected_->verify)
                encoder->private_->verify.state_hint = ENCODER_IN_MAGIC;
-       if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+       if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN)) {
+               encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
        if(!write_bitbuffer_(encoder, 0)) {
                /* the above function sets the state for us in case of an error */
-               return encoder->protected_->state;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
        }
 
        /*
@@ -923,35 +974,39 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
         */
        if(encoder->protected_->verify)
                encoder->private_->verify.state_hint = ENCODER_IN_METADATA;
-       encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
-       encoder->private_->metadata.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */
-       encoder->private_->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
-       encoder->private_->metadata.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
-       encoder->private_->metadata.data.stream_info.max_blocksize = encoder->protected_->blocksize;
-       encoder->private_->metadata.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
-       encoder->private_->metadata.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
-       encoder->private_->metadata.data.stream_info.sample_rate = encoder->protected_->sample_rate;
-       encoder->private_->metadata.data.stream_info.channels = encoder->protected_->channels;
-       encoder->private_->metadata.data.stream_info.bits_per_sample = encoder->protected_->bits_per_sample;
-       encoder->private_->metadata.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */
-       memset(encoder->private_->metadata.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
+       encoder->private_->streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
+       encoder->private_->streaminfo.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */
+       encoder->private_->streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
+       encoder->private_->streaminfo.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
+       encoder->private_->streaminfo.data.stream_info.max_blocksize = encoder->protected_->blocksize;
+       encoder->private_->streaminfo.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */
+       encoder->private_->streaminfo.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */
+       encoder->private_->streaminfo.data.stream_info.sample_rate = encoder->protected_->sample_rate;
+       encoder->private_->streaminfo.data.stream_info.channels = encoder->protected_->channels;
+       encoder->private_->streaminfo.data.stream_info.bits_per_sample = encoder->protected_->bits_per_sample;
+       encoder->private_->streaminfo.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */
+       memset(encoder->private_->streaminfo.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */
        FLAC__MD5Init(&encoder->private_->md5context);
-       if(!FLAC__bitbuffer_clear(encoder->private_->frame))
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
-       if(!FLAC__add_metadata_block(&encoder->private_->metadata, encoder->private_->frame))
-               return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+       if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
+               encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
+       if(!FLAC__add_metadata_block(&encoder->private_->streaminfo, encoder->private_->frame)) {
+               encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
        if(!write_bitbuffer_(encoder, 0)) {
                /* the above function sets the state for us in case of an error */
-               return encoder->protected_->state;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
        }
 
        /*
         * Now that the STREAMINFO block is written, we can init this to an
         * absurdly-high value...
         */
-       encoder->private_->metadata.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1;
+       encoder->private_->streaminfo.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1;
        /* ... and clear this to 0 */
-       encoder->private_->metadata.data.stream_info.total_samples = 0;
+       encoder->private_->streaminfo.data.stream_info.total_samples = 0;
 
        /*
         * Check to see if the supplied metadata contains a VORBIS_COMMENT;
@@ -972,13 +1027,17 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
                vorbis_comment.data.vorbis_comment.vendor_string.entry = 0;
                vorbis_comment.data.vorbis_comment.num_comments = 0;
                vorbis_comment.data.vorbis_comment.comments = 0;
-               if(!FLAC__bitbuffer_clear(encoder->private_->frame))
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
-               if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame))
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+               if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+               }
+               if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame)) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+               }
                if(!write_bitbuffer_(encoder, 0)) {
                        /* the above function sets the state for us in case of an error */
-                       return encoder->protected_->state;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
                }
        }
 
@@ -987,25 +1046,108 @@ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder
         */
        for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
                encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1);
-               if(!FLAC__bitbuffer_clear(encoder->private_->frame))
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
-               if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame))
-                       return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+               if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+               }
+               if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame)) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+               }
                if(!write_bitbuffer_(encoder, 0)) {
                        /* the above function sets the state for us in case of an error */
-                       return encoder->protected_->state;
+                       return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
                }
        }
 
+       /* now that all the metadata is written, we save the stream offset */
+       if(encoder->private_->tell_callback && encoder->private_->tell_callback(encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */
+               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
+
        if(encoder->protected_->verify)
                encoder->private_->verify.state_hint = ENCODER_IN_AUDIO;
 
-       return encoder->protected_->state;
+       return FLAC__STREAM_ENCODER_INIT_STATUS_OK;
+}
+
+FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_FILE(FLAC__StreamEncoder *encoder, FILE *file, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data)
+{
+       FLAC__StreamEncoderInitStatus init_status;
+
+       FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != file);
+
+       /*
+        * To make sure that our file does not go unclosed after an error, we
+        * must assign the FILE pointer before any further error can occur in
+        * this routine.
+        */
+       if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
+
+       /* double protection */
+       if(file == 0) {
+               encoder->protected_->state = FLAC__STREAM_ENCODER_IO_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
+
+       if(file == stdout)
+               file = get_binary_stdout_(); /* just to be safe */
+
+       encoder->private_->file = file;
+
+       encoder->private_->progress_callback = progress_callback;
+       encoder->private_->bytes_written = 0;
+       encoder->private_->samples_written = 0;
+       encoder->private_->frames_written = 0;
+
+       init_status = FLAC__stream_encoder_init_stream(encoder, file_write_callback_, file_seek_callback_, file_tell_callback_, /*metadata_callback=*/0, client_data);
+       if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
+               /* the above function sets the state for us in case of an error */
+               return init_status;
+       }
+
+       {
+               unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder);
+
+               FLAC__ASSERT(blocksize != 0);
+               encoder->private_->total_frames_estimate = (unsigned)((FLAC__stream_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize);
+       }
+
+       return init_status;
+}
+
+FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file(FLAC__StreamEncoder *encoder, const char *filename, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data)
+{
+       FILE *file;
+
+       FLAC__ASSERT(0 != encoder);
+
+       /*
+        * To make sure that our file does not go unclosed after an error, we
+        * have to do the same entrance checks here that are later performed
+        * in FLAC__stream_encoder_init_FILE() before the FILE* is assigned.
+        */
+       if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
+
+       file = filename? fopen(filename, "w+b") : stdout;
+
+       if(file == 0) {
+               encoder->protected_->state = FLAC__STREAM_ENCODER_IO_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
+
+       return FLAC__stream_encoder_init_FILE(encoder, file, progress_callback, client_data);
 }
 
 FLAC_API void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
 {
        FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != encoder->private_);
+       FLAC__ASSERT(0 != encoder->protected_);
 
        if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED)
                return;
@@ -1017,15 +1159,24 @@ FLAC_API void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder)
                }
        }
 
-       FLAC__MD5Final(encoder->private_->metadata.data.stream_info.md5sum, &encoder->private_->md5context);
+       FLAC__MD5Final(encoder->private_->streaminfo.data.stream_info.md5sum, &encoder->private_->md5context);
 
        if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) {
-               encoder->private_->metadata_callback(encoder, &encoder->private_->metadata, encoder->private_->client_data);
+               if(encoder->private_->seek_callback)
+                       update_metadata_(encoder);
+               if(encoder->private_->metadata_callback)
+                       encoder->private_->metadata_callback(encoder, &encoder->private_->streaminfo, encoder->private_->client_data);
        }
 
        if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder)
                FLAC__stream_decoder_finish(encoder->private_->verify.decoder);
 
+       if(0 != encoder->private_->file) {
+               if(encoder->private_->file != stdout)
+                       fclose(encoder->private_->file);
+               encoder->private_->file = 0;
+       }
+
        free_(encoder);
        set_defaults_(encoder);
 
@@ -1276,35 +1427,15 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encod
                return false;
        encoder->protected_->metadata = metadata;
        encoder->protected_->num_metadata_blocks = num_blocks;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__stream_encoder_set_write_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->write_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderMetadataCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->metadata_callback = value;
-       return true;
-}
-
-FLAC_API FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, void *value)
-{
-       FLAC__ASSERT(0 != encoder);
-       if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->client_data = value;
+       if(0 != metadata && num_blocks > 0) {
+               unsigned i;
+               for(i = 0; i < num_blocks; i++) {
+                       if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
+                               encoder->private_->seek_table = &metadata[i]->data.seek_table;
+                               break; /* take only the first one */
+                       }
+               }
+       }
        return true;
 }
 
@@ -1780,11 +1911,15 @@ void set_defaults_(FLAC__StreamEncoder *encoder)
        encoder->protected_->metadata = 0;
        encoder->protected_->num_metadata_blocks = 0;
 
+       encoder->private_->seek_table = 0;
        encoder->private_->disable_constant_subframes = false;
        encoder->private_->disable_fixed_subframes = false;
        encoder->private_->disable_verbatim_subframes = false;
        encoder->private_->write_callback = 0;
+       encoder->private_->seek_callback = 0;
+       encoder->private_->tell_callback = 0;
        encoder->private_->metadata_callback = 0;
+       encoder->private_->progress_callback = 0;
        encoder->private_->client_data = 0;
 }
 
@@ -2022,22 +2157,250 @@ FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples)
                }
        }
 
-       if(encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
+       if(write_frame_(encoder, buffer, bytes, samples) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
                FLAC__bitbuffer_release_buffer(encoder->private_->frame);
-               encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING;
+               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
                return false;
        }
 
        FLAC__bitbuffer_release_buffer(encoder->private_->frame);
 
        if(samples > 0) {
-               encoder->private_->metadata.data.stream_info.min_framesize = min(bytes, encoder->private_->metadata.data.stream_info.min_framesize);
-               encoder->private_->metadata.data.stream_info.max_framesize = max(bytes, encoder->private_->metadata.data.stream_info.max_framesize);
+               encoder->private_->streaminfo.data.stream_info.min_framesize = min(bytes, encoder->private_->streaminfo.data.stream_info.min_framesize);
+               encoder->private_->streaminfo.data.stream_info.max_framesize = max(bytes, encoder->private_->streaminfo.data.stream_info.max_framesize);
        }
 
        return true;
 }
 
+FLAC__StreamEncoderWriteStatus write_frame_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples)
+{
+       FLAC__StreamEncoderWriteStatus status;
+       FLAC__uint64 output_position = 0;
+
+       /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */
+       if(encoder->private_->tell_callback && encoder->private_->tell_callback(encoder, &output_position, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) {
+               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
+       }
+
+       /*
+        * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets.
+        */
+       if(samples == 0) {
+               FLAC__MetadataType type = (buffer[0] & 0x7f);
+               if(type == FLAC__METADATA_TYPE_STREAMINFO)
+                       encoder->protected_->streaminfo_offset = output_position;
+               else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0)
+                       encoder->protected_->seektable_offset = output_position;
+       }
+
+       /*
+        * Mark the current seek point if hit (if audio_offset == 0 that
+        * means we're still writing metadata and haven't hit the first
+        * frame yet)
+        */
+       if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) {
+               const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder);
+               const FLAC__uint64 frame_first_sample = encoder->private_->samples_written;
+               const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
+               FLAC__uint64 test_sample;
+               unsigned i;
+               for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) {
+                       test_sample = encoder->private_->seek_table->points[i].sample_number;
+                       if(test_sample > frame_last_sample) {
+                               break;
+                       }
+                       else if(test_sample >= frame_first_sample) {
+                               encoder->private_->seek_table->points[i].sample_number = frame_first_sample;
+                               encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset;
+                               encoder->private_->seek_table->points[i].frame_samples = blocksize;
+                               encoder->private_->first_seekpoint_to_check++;
+                               /* DO NOT: "break;" and here's why:
+                                * The seektable template may contain more than one target
+                                * sample for any given frame; we will keep looping, generating
+                                * duplicate seekpoints for them, and we'll clean it up later,
+                                * just before writing the seektable back to the metadata.
+                                */
+                       }
+                       else {
+                               encoder->private_->first_seekpoint_to_check++;
+                       }
+               }
+       }
+
+       status = encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data);
+
+       if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
+               encoder->private_->bytes_written += bytes;
+               encoder->private_->samples_written += samples;
+               /* we keep a high watermark on the number of frames written because
+                * when the encoder goes back to write metadata, 'current_frame'
+                * will drop back to 0.
+                */
+               encoder->private_->frames_written = max(encoder->private_->frames_written, encoder->private_->current_frame_number+1);
+       }
+       else
+               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+
+       return status;
+}
+
+/* Gets called when the encoding process has finished so that we can update the STREAMINFO and SEEKTABLE blocks.  */
+void update_metadata_(const FLAC__StreamEncoder *encoder)
+{
+       FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)];
+       const FLAC__StreamMetadata *metadata = &encoder->private_->streaminfo;
+       const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
+       const unsigned min_framesize = metadata->data.stream_info.min_framesize;
+       const unsigned max_framesize = metadata->data.stream_info.max_framesize;
+       const unsigned bps = metadata->data.stream_info.bits_per_sample;
+       FLAC__StreamEncoderSeekStatus seek_status;
+
+       FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
+
+       /* All this is based on intimate knowledge of the stream header
+        * layout, but a change to the header format that would break this
+        * would also break all streams encoded in the previous format.
+        */
+
+       /*
+        * Write MD5 signature
+        */
+       {
+               const unsigned md5_offset =
+                       FLAC__STREAM_METADATA_HEADER_LENGTH +
+                       (
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
+                       ) / 8;
+
+               if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + md5_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
+                       if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+                       return;
+               }
+               if(encoder->private_->write_callback(encoder, metadata->data.stream_info.md5sum, 16, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+                       return;
+               }
+       }
+
+       /*
+        * Write total samples
+        */
+       {
+               const unsigned total_samples_byte_offset =
+                       FLAC__STREAM_METADATA_HEADER_LENGTH +
+                       (
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
+                               - 4
+                       ) / 8;
+
+               b[0] = ((FLAC__byte)(bps-1) << 4) | (FLAC__byte)((samples >> 32) & 0x0F);
+               b[1] = (FLAC__byte)((samples >> 24) & 0xFF);
+               b[2] = (FLAC__byte)((samples >> 16) & 0xFF);
+               b[3] = (FLAC__byte)((samples >> 8) & 0xFF);
+               b[4] = (FLAC__byte)(samples & 0xFF);
+               if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + total_samples_byte_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
+                       if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+                       return;
+               }
+               if(encoder->private_->write_callback(encoder, b, 5, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+                       return;
+               }
+       }
+
+       /*
+        * Write min/max framesize
+        */
+       {
+               const unsigned min_framesize_offset =
+                       FLAC__STREAM_METADATA_HEADER_LENGTH +
+                       (
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
+                       ) / 8;
+
+               b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF);
+               b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF);
+               b[2] = (FLAC__byte)(min_framesize & 0xFF);
+               b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF);
+               b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF);
+               b[5] = (FLAC__byte)(max_framesize & 0xFF);
+               if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + min_framesize_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
+                       if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+                       return;
+               }
+               if(encoder->private_->write_callback(encoder, b, 6, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+                       return;
+               }
+       }
+
+       /*
+        * Write seektable
+        */
+       if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) {
+               unsigned i;
+
+               FLAC__format_seektable_sort(encoder->private_->seek_table);
+
+               FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table));
+
+               if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->seektable_offset + FLAC__STREAM_METADATA_HEADER_LENGTH, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
+                       if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+                       return;
+               }
+
+               for(i = 0; i < encoder->private_->seek_table->num_points; i++) {
+                       FLAC__uint64 xx;
+                       unsigned x;
+                       xx = encoder->private_->seek_table->points[i].sample_number;
+                       b[7] = (FLAC__byte)xx; xx >>= 8;
+                       b[6] = (FLAC__byte)xx; xx >>= 8;
+                       b[5] = (FLAC__byte)xx; xx >>= 8;
+                       b[4] = (FLAC__byte)xx; xx >>= 8;
+                       b[3] = (FLAC__byte)xx; xx >>= 8;
+                       b[2] = (FLAC__byte)xx; xx >>= 8;
+                       b[1] = (FLAC__byte)xx; xx >>= 8;
+                       b[0] = (FLAC__byte)xx; xx >>= 8;
+                       xx = encoder->private_->seek_table->points[i].stream_offset;
+                       b[15] = (FLAC__byte)xx; xx >>= 8;
+                       b[14] = (FLAC__byte)xx; xx >>= 8;
+                       b[13] = (FLAC__byte)xx; xx >>= 8;
+                       b[12] = (FLAC__byte)xx; xx >>= 8;
+                       b[11] = (FLAC__byte)xx; xx >>= 8;
+                       b[10] = (FLAC__byte)xx; xx >>= 8;
+                       b[9] = (FLAC__byte)xx; xx >>= 8;
+                       b[8] = (FLAC__byte)xx; xx >>= 8;
+                       x = encoder->private_->seek_table->points[i].frame_samples;
+                       b[17] = (FLAC__byte)x; x >>= 8;
+                       b[16] = (FLAC__byte)x; x >>= 8;
+                       if(encoder->private_->write_callback(encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
+                               return;
+                       }
+               }
+       }
+}
+
 FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame)
 {
        FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK);
@@ -2085,7 +2448,7 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame
         */
        encoder->private_->current_sample_number = 0;
        encoder->private_->current_frame_number++;
-       encoder->private_->metadata.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize;
+       encoder->private_->streaminfo.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize;
 
        return true;
 }
@@ -2634,13 +2997,13 @@ FLAC__bool add_subframe_(
        switch(subframe->type) {
                case FLAC__SUBFRAME_TYPE_CONSTANT:
                        if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) {
-                               encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
                                return false;
                        }
                        break;
                case FLAC__SUBFRAME_TYPE_FIXED:
                        if(!FLAC__subframe_add_fixed(&(subframe->data.fixed), frame_header->blocksize - subframe->data.fixed.order, subframe_bps, subframe->wasted_bits, frame)) {
-                               encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
                                return false;
                        }
                        break;
@@ -2649,13 +3012,13 @@ FLAC__bool add_subframe_(
                        fprintf(stderr, "WIN:\tframe=%u\tsubframe=?\torder=%u\twindow=%s\tbits=%u\n", frame_header->number.frame_number, subframe->data.lpc.order, subframe->data.lpc.window_type, subframe_bits);
 #endif
                        if(!FLAC__subframe_add_lpc(&(subframe->data.lpc), frame_header->blocksize - subframe->data.lpc.order, subframe_bps, subframe->wasted_bits, frame)) {
-                               encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
                                return false;
                        }
                        break;
                case FLAC__SUBFRAME_TYPE_VERBATIM:
                        if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), frame_header->blocksize, subframe_bps, subframe->wasted_bits, frame)) {
-                               encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_ENCODING;
+                               encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
                                return false;
                        }
                        break;
@@ -3612,3 +3975,76 @@ void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDeco
        (void)decoder, (void)status;
        encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
 }
+
+FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+       (void)client_data;
+
+       if(fseeko(encoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
+               return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
+       else
+               return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+}
+
+FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+       off_t offset;
+
+       (void)client_data;
+
+       offset = ftello(encoder->private_->file);
+
+       if(offset < 0) {
+               return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
+       }
+       else {
+               *absolute_byte_offset = (FLAC__uint64)offset;
+               return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+       }
+}
+
+#ifdef FLAC__VALGRIND_TESTING
+static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+       size_t ret = fwrite(ptr, size, nmemb, stream);
+       if(!ferror(stream))
+               fflush(stream);
+       return ret;
+}
+#else
+#define local__fwrite fwrite
+#endif
+
+FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
+{
+       (void)client_data, (void)samples, (void)current_frame;
+
+       if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, encoder->private_->file) == bytes) {
+               if(0 != encoder->private_->progress_callback && samples > 0)
+                       encoder->private_->progress_callback(encoder, encoder->private_->bytes_written, encoder->private_->samples_written, encoder->private_->frames_written, encoder->private_->total_frames_estimate, encoder->private_->client_data);
+               return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+       }
+       else
+               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
+}
+
+/*
+ * This will forcibly set stdout to binary mode (for OSes that require it)
+ */
+FILE *get_binary_stdout_()
+{
+       /* if something breaks here it is probably due to the presence or
+        * absence of an underscore before the identifiers 'setmode',
+        * 'fileno', and/or 'O_BINARY'; check your system header files.
+        */
+#if defined _MSC_VER || defined __MINGW32__
+       _setmode(_fileno(stdout), _O_BINARY);
+#elif defined __CYGWIN__
+       /* almost certainly not needed for any modern Cygwin, but let's be safe... */
+       setmode(_fileno(stdout), _O_BINARY);
+#elif defined __EMX__
+       setmode(fileno(stdout), O_BINARY);
+#endif
+
+       return stdout;
+}
index e4714ac..873fb0c 100644 (file)
@@ -46,7 +46,5 @@ libOggFLAC___la_LIBADD = ../libOggFLAC/libOggFLAC.la
 libOggFLAC___la_SOURCES = \
        file_decoder.cpp \
        file_encoder.cpp \
-       seekable_stream_decoder.cpp \
-       seekable_stream_encoder.cpp \
        stream_decoder.cpp \
        stream_encoder.cpp
index a1a665e..e5dd81d 100644 (file)
@@ -40,8 +40,6 @@ INCLUDES = -I$(topdir)/include
 SRCS_CPP = \
        file_decoder.cpp \
        file_encoder.cpp \
-       seekable_stream_decoder.cpp \
-       seekable_stream_encoder.cpp \
        stream_decoder.cpp \
        stream_encoder.cpp
 
index d35d7c5..cc83255 100644 (file)
@@ -41,201 +41,40 @@ namespace OggFLAC {
        namespace Decoder {
 
                File::File():
-               decoder_(::OggFLAC__file_decoder_new())
+                       Stream()
                { }
 
                File::~File()
                {
-                       if(0 != decoder_) {
-                               (void) ::OggFLAC__file_decoder_finish(decoder_);
-                               ::OggFLAC__file_decoder_delete(decoder_);
-                       }
                }
 
-               bool File::is_valid() const
-               {
-                       return 0 != decoder_;
-               }
-
-               bool File::set_serial_number(long value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_decoder_set_serial_number(decoder_, value);
-               }
-
-               bool File::set_md5_checking(bool value)
+               ::FLAC__StreamDecoderInitStatus File::init(FILE *file)
                {
                        FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_set_md5_checking(decoder_, value);
+                       return ::OggFLAC__stream_decoder_init_FILE(decoder_, file, write_callback_, metadata_callback_, error_callback_, /*client_data=*/(void*)this);
                }
 
-               bool File::set_filename(const char *value)
+               ::FLAC__StreamDecoderInitStatus File::init(const char *filename)
                {
                        FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_set_filename(decoder_, value);
-               }
-
-               bool File::set_metadata_respond(::FLAC__MetadataType type)
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_set_metadata_respond(decoder_, type);
-               }
-
-               bool File::set_metadata_respond_application(const FLAC__byte id[4])
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_set_metadata_respond_application(decoder_, id);
-               }
-
-               bool File::set_metadata_respond_all()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_set_metadata_respond_all(decoder_);
-               }
-
-               bool File::set_metadata_ignore(::FLAC__MetadataType type)
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_set_metadata_ignore(decoder_, type);
-               }
-
-               bool File::set_metadata_ignore_application(const FLAC__byte id[4])
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_set_metadata_ignore_application(decoder_, id);
-               }
-
-               bool File::set_metadata_ignore_all()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_set_metadata_ignore_all(decoder_);
-               }
-
-               File::State File::get_state() const
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return State(::OggFLAC__file_decoder_get_state(decoder_));
-               }
-
-               OggFLAC::Decoder::SeekableStream::State File::get_seekable_stream_decoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return OggFLAC::Decoder::SeekableStream::State(::OggFLAC__file_decoder_get_seekable_stream_decoder_state(decoder_));
-               }
-
-               OggFLAC::Decoder::Stream::State File::get_stream_decoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return OggFLAC::Decoder::Stream::State(::OggFLAC__file_decoder_get_stream_decoder_state(decoder_));
-               }
-
-               FLAC::Decoder::Stream::State File::get_FLAC_stream_decoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return FLAC::Decoder::Stream::State(::OggFLAC__file_decoder_get_FLAC_stream_decoder_state(decoder_));
-               }
-
-               bool File::get_md5_checking() const
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_get_md5_checking(decoder_);
-               }
-
-               unsigned File::get_channels() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_decoder_get_channels(decoder_);
-               }
-
-               ::FLAC__ChannelAssignment File::get_channel_assignment() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_decoder_get_channel_assignment(decoder_);
-               }
-
-               unsigned File::get_bits_per_sample() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_decoder_get_bits_per_sample(decoder_);
-               }
-
-               unsigned File::get_sample_rate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_decoder_get_sample_rate(decoder_);
-               }
-
-               unsigned File::get_blocksize() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_decoder_get_blocksize(decoder_);
-               }
-
-               File::State File::init()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       ::OggFLAC__file_decoder_set_write_callback(decoder_, write_callback_);
-                       ::OggFLAC__file_decoder_set_metadata_callback(decoder_, metadata_callback_);
-                       ::OggFLAC__file_decoder_set_error_callback(decoder_, error_callback_);
-                       ::OggFLAC__file_decoder_set_client_data(decoder_, (void*)this);
-                       return State(::OggFLAC__file_decoder_init(decoder_));
-               }
-
-               bool File::finish()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_finish(decoder_);
-               }
-
-               bool File::process_single()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_process_single(decoder_);
-               }
-
-               bool File::process_until_end_of_metadata()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_process_until_end_of_metadata(decoder_);
-               }
-
-               bool File::process_until_end_of_file()
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_process_until_end_of_file(decoder_);
-               }
-
-               bool File::seek_absolute(FLAC__uint64 sample)
-               {
-                       FLAC__ASSERT(0 != decoder_);
-                       return (bool)::OggFLAC__file_decoder_seek_absolute(decoder_, sample);
-               }
-
-               ::FLAC__StreamDecoderWriteStatus File::write_callback_(const ::OggFLAC__FileDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       File *instance = reinterpret_cast<File *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->write_callback(frame, buffer);
+                       return ::OggFLAC__stream_decoder_init_file(decoder_, filename, write_callback_, metadata_callback_, error_callback_, /*client_data=*/(void*)this);
                }
 
-               void File::metadata_callback_(const ::OggFLAC__FileDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
+               ::FLAC__StreamDecoderInitStatus File::init(const std::string &filename)
                {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       File *instance = reinterpret_cast<File *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       instance->metadata_callback(metadata);
+                       return init(filename.c_str());
                }
 
-               void File::error_callback_(const ::OggFLAC__FileDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data)
+               // This is a dummy to satisfy the pure virtual from Stream; the
+               // read callback will never be called since we are initializing
+               // with FLAC__stream_decoder_init_FILE() or
+               // FLAC__stream_decoder_init_file() and those supply the read
+               // callback internally.
+               ::FLAC__StreamDecoderReadStatus File::read_callback(FLAC__byte buffer[], unsigned *bytes)
                {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       File *instance = reinterpret_cast<File *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       instance->error_callback(status);
+                       (void)buffer, (void)bytes;
+                       FLAC__ASSERT(false);
+                       return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; // double protection
                }
 
        }
index ee921c0..1f23d7d 100644 (file)
@@ -41,304 +41,40 @@ namespace OggFLAC {
        namespace Encoder {
 
                File::File():
-               encoder_(::OggFLAC__file_encoder_new())
+                       Stream()
                { }
 
                File::~File()
                {
-                       if(0 != encoder_) {
-                               ::OggFLAC__file_encoder_finish(encoder_);
-                               ::OggFLAC__file_encoder_delete(encoder_);
-                       }
                }
 
-               bool File::set_serial_number(long value)
+               ::FLAC__StreamEncoderInitStatus File::init(FILE *file)
                {
                        FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_serial_number(encoder_, value);
+                       return ::OggFLAC__stream_encoder_init_FILE(encoder_, file, progress_callback_, /*client_data=*/(void*)this);
                }
 
-               bool File::is_valid() const
-               {
-                       return 0 != encoder_;
-               }
-
-               bool File::set_verify(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_verify(encoder_, value);
-               }
-
-               bool File::set_streamable_subset(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_streamable_subset(encoder_, value);
-               }
-
-               bool File::set_do_mid_side_stereo(bool value)
+               ::FLAC__StreamEncoderInitStatus File::init(const char *filename)
                {
                        FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_do_mid_side_stereo(encoder_, value);
+                       return ::OggFLAC__stream_encoder_init_file(encoder_, filename, progress_callback_, /*client_data=*/(void*)this);
                }
 
-               bool File::set_loose_mid_side_stereo(bool value)
+               ::FLAC__StreamEncoderInitStatus File::init(const std::string &filename)
                {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_loose_mid_side_stereo(encoder_, value);
+                       return init(filename.c_str());
                }
 
-               bool File::set_channels(unsigned value)
+               // This is a dummy to satisfy the pure virtual from Stream; the
+               // read callback will never be called since we are initializing
+               // with OggFLAC__stream_decoder_init_FILE() or
+               // OggFLAC__stream_decoder_init_file() and those supply the read
+               // callback internally.
+               ::FLAC__StreamEncoderWriteStatus File::write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame)
                {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_channels(encoder_, value);
-               }
-
-               bool File::set_bits_per_sample(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_bits_per_sample(encoder_, value);
-               }
-
-               bool File::set_sample_rate(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_sample_rate(encoder_, value);
-               }
-
-               bool File::set_blocksize(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_blocksize(encoder_, value);
-               }
-
-               bool File::set_apodization(const char *specification)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_apodization(encoder_, specification);
-               }
-
-               bool File::set_max_lpc_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_max_lpc_order(encoder_, value);
-               }
-
-               bool File::set_qlp_coeff_precision(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_qlp_coeff_precision(encoder_, value);
-               }
-
-               bool File::set_do_qlp_coeff_prec_search(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(encoder_, value);
-               }
-
-               bool File::set_do_escape_coding(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_do_escape_coding(encoder_, value);
-               }
-
-               bool File::set_do_exhaustive_model_search(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_do_exhaustive_model_search(encoder_, value);
-               }
-
-               bool File::set_min_residual_partition_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_min_residual_partition_order(encoder_, value);
-               }
-
-               bool File::set_max_residual_partition_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_max_residual_partition_order(encoder_, value);
-               }
-
-               bool File::set_rice_parameter_search_dist(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_rice_parameter_search_dist(encoder_, value);
-               }
-
-               bool File::set_total_samples_estimate(FLAC__uint64 value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_total_samples_estimate(encoder_, value);
-               }
-
-               bool File::set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_metadata(encoder_, metadata, num_blocks);
-               }
-
-               bool File::set_filename(const char *value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_set_filename(encoder_, value);
-               }
-
-               File::State File::get_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return State(::OggFLAC__file_encoder_get_state(encoder_));
-               }
-
-               SeekableStream::State File::get_seekable_stream_encoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return SeekableStream::State(::OggFLAC__file_encoder_get_seekable_stream_encoder_state(encoder_));
-               }
-
-               FLAC::Encoder::Stream::State File::get_FLAC_stream_encoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return FLAC::Encoder::Stream::State(::OggFLAC__file_encoder_get_FLAC_stream_encoder_state(encoder_));
-               }
-
-               FLAC::Decoder::Stream::State File::get_verify_decoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return FLAC::Decoder::Stream::State(::OggFLAC__file_encoder_get_verify_decoder_state(encoder_));
-               }
-
-               void File::get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::OggFLAC__file_encoder_get_verify_decoder_error_stats(encoder_, absolute_sample, frame_number, channel, sample, expected, got);
-               }
-
-               bool File::get_verify() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_get_verify(encoder_);
-               }
-
-               bool File::get_streamable_subset() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_get_streamable_subset(encoder_);
-               }
-
-               bool File::get_do_mid_side_stereo() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_get_do_mid_side_stereo(encoder_);
-               }
-
-               bool File::get_loose_mid_side_stereo() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_get_loose_mid_side_stereo(encoder_);
-               }
-
-               unsigned File::get_channels() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_channels(encoder_);
-               }
-
-               unsigned File::get_bits_per_sample() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_bits_per_sample(encoder_);
-               }
-
-               unsigned File::get_sample_rate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_sample_rate(encoder_);
-               }
-
-               unsigned File::get_blocksize() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_blocksize(encoder_);
-               }
-
-               unsigned File::get_max_lpc_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_max_lpc_order(encoder_);
-               }
-
-               unsigned File::get_qlp_coeff_precision() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_qlp_coeff_precision(encoder_);
-               }
-
-               bool File::get_do_qlp_coeff_prec_search() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_get_do_qlp_coeff_prec_search(encoder_);
-               }
-
-               bool File::get_do_escape_coding() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_get_do_escape_coding(encoder_);
-               }
-
-               bool File::get_do_exhaustive_model_search() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_get_do_exhaustive_model_search(encoder_);
-               }
-
-               unsigned File::get_min_residual_partition_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_min_residual_partition_order(encoder_);
-               }
-
-               unsigned File::get_max_residual_partition_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_max_residual_partition_order(encoder_);
-               }
-
-               unsigned File::get_rice_parameter_search_dist() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_rice_parameter_search_dist(encoder_);
-               }
-
-               FLAC__uint64 File::get_total_samples_estimate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__file_encoder_get_total_samples_estimate(encoder_);
-               }
-
-               File::State File::init()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::OggFLAC__file_encoder_set_progress_callback(encoder_, progress_callback_);
-                       ::OggFLAC__file_encoder_set_client_data(encoder_, (void*)this);
-                       return State(::OggFLAC__file_encoder_init(encoder_));
-               }
-
-               void File::finish()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::OggFLAC__file_encoder_finish(encoder_);
-               }
-
-               bool File::process(const FLAC__int32 * const buffer[], unsigned samples)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_process(encoder_, buffer, samples);
-               }
-
-               bool File::process_interleaved(const FLAC__int32 buffer[], unsigned samples)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__file_encoder_process_interleaved(encoder_, buffer, samples);
+                       (void)buffer, (void)bytes, (void)samples, (void)current_frame;
+                       FLAC__ASSERT(false);
+                       return ::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; // double protection
                }
 
                void File::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate)
@@ -346,7 +82,7 @@ namespace OggFLAC {
                        (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate;
                }
 
-               void File::progress_callback_(const ::OggFLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
+               void File::progress_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
                {
                        (void)encoder;
                        FLAC__ASSERT(0 != client_data);
index 1c13d34..ef52d26 100644 (file)
@@ -100,14 +100,6 @@ SOURCE=.\file_encoder.cpp
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\seekable_stream_decoder.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\seekable_stream_encoder.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\stream_decoder.cpp\r
 # End Source File\r
 # Begin Source File\r
index 0331571..573a97d 100644 (file)
@@ -93,14 +93,6 @@ SOURCE=.\file_encoder.cpp
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\seekable_stream_decoder.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\seekable_stream_encoder.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\stream_decoder.cpp\r
 # End Source File\r
 # Begin Source File\r
diff --git a/src/libOggFLAC++/seekable_stream_decoder.cpp b/src/libOggFLAC++/seekable_stream_decoder.cpp
deleted file mode 100644 (file)
index fa910ca..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/* libOggFLAC++ - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "OggFLAC++/decoder.h"
-#include "FLAC/assert.h"
-
-#ifdef _MSC_VER
-// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
-#pragma warning ( disable : 4800 )
-#endif
-
-namespace OggFLAC {
-       namespace Decoder {
-
-               SeekableStream::SeekableStream():
-               decoder_(::OggFLAC__seekable_stream_decoder_new())
-               { }
-
-               SeekableStream::~SeekableStream()
-               {
-                       if(0 != decoder_) {
-                               (void) ::OggFLAC__seekable_stream_decoder_finish(decoder_);
-                               ::OggFLAC__seekable_stream_decoder_delete(decoder_);
-                       }
-               }
-
-               bool SeekableStream::is_valid() const
-               {
-                       return 0 != decoder_;
-               }
-
-               bool SeekableStream::set_serial_number(long value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_set_serial_number(decoder_, value);
-               }
-
-               bool SeekableStream::set_md5_checking(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_set_md5_checking(decoder_, value);
-               }
-
-               bool SeekableStream::set_metadata_respond(::FLAC__MetadataType type)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder_, type);
-               }
-
-               bool SeekableStream::set_metadata_respond_application(const FLAC__byte id[4])
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_set_metadata_respond_application(decoder_, id);
-               }
-
-               bool SeekableStream::set_metadata_respond_all()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder_);
-               }
-
-               bool SeekableStream::set_metadata_ignore(::FLAC__MetadataType type)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_set_metadata_ignore(decoder_, type);
-               }
-
-               bool SeekableStream::set_metadata_ignore_application(const FLAC__byte id[4])
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder_, id);
-               }
-
-               bool SeekableStream::set_metadata_ignore_all()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder_);
-               }
-
-               SeekableStream::State SeekableStream::get_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return State(::OggFLAC__seekable_stream_decoder_get_state(decoder_));
-               }
-
-               OggFLAC::Decoder::Stream::State SeekableStream::get_stream_decoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       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
-               {
-                       FLAC__ASSERT(is_valid());
-                       return FLAC::Decoder::Stream::State(::OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(decoder_));
-               }
-
-               bool SeekableStream::get_md5_checking() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_get_md5_checking(decoder_);
-               }
-
-               unsigned SeekableStream::get_channels() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_decoder_get_channels(decoder_);
-               }
-
-               ::FLAC__ChannelAssignment SeekableStream::get_channel_assignment() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_decoder_get_channel_assignment(decoder_);
-               }
-
-               unsigned SeekableStream::get_bits_per_sample() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_decoder_get_bits_per_sample(decoder_);
-               }
-
-               unsigned SeekableStream::get_sample_rate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_decoder_get_sample_rate(decoder_);
-               }
-
-               unsigned SeekableStream::get_blocksize() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_decoder_get_blocksize(decoder_);
-               }
-
-               SeekableStream::State SeekableStream::init()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::OggFLAC__seekable_stream_decoder_set_read_callback(decoder_, read_callback_);
-                       ::OggFLAC__seekable_stream_decoder_set_seek_callback(decoder_, seek_callback_);
-                       ::OggFLAC__seekable_stream_decoder_set_tell_callback(decoder_, tell_callback_);
-                       ::OggFLAC__seekable_stream_decoder_set_length_callback(decoder_, length_callback_);
-                       ::OggFLAC__seekable_stream_decoder_set_eof_callback(decoder_, eof_callback_);
-                       ::OggFLAC__seekable_stream_decoder_set_write_callback(decoder_, write_callback_);
-                       ::OggFLAC__seekable_stream_decoder_set_metadata_callback(decoder_, metadata_callback_);
-                       ::OggFLAC__seekable_stream_decoder_set_error_callback(decoder_, error_callback_);
-                       ::OggFLAC__seekable_stream_decoder_set_client_data(decoder_, (void*)this);
-                       return State(::OggFLAC__seekable_stream_decoder_init(decoder_));
-               }
-
-               bool SeekableStream::finish()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_finish(decoder_);
-               }
-
-               bool SeekableStream::flush()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_flush(decoder_);
-               }
-
-               bool SeekableStream::reset()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_reset(decoder_);
-               }
-
-               bool SeekableStream::process_single()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_process_single(decoder_);
-               }
-
-               bool SeekableStream::process_until_end_of_metadata()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder_);
-               }
-
-               bool SeekableStream::process_until_end_of_stream()
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_process_until_end_of_stream(decoder_);
-               }
-
-               bool SeekableStream::seek_absolute(FLAC__uint64 sample)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_decoder_seek_absolute(decoder_, sample);
-               }
-
-               ::OggFLAC__SeekableStreamDecoderReadStatus SeekableStream::read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->read_callback(buffer, bytes);
-               }
-
-               ::OggFLAC__SeekableStreamDecoderSeekStatus SeekableStream::seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->seek_callback(absolute_byte_offset);
-               }
-
-               ::OggFLAC__SeekableStreamDecoderTellStatus SeekableStream::tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->tell_callback(absolute_byte_offset);
-               }
-
-               ::OggFLAC__SeekableStreamDecoderLengthStatus SeekableStream::length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->length_callback(stream_length);
-               }
-
-               FLAC__bool SeekableStream::eof_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->eof_callback();
-               }
-
-               ::FLAC__StreamDecoderWriteStatus SeekableStream::write_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->write_callback(frame, buffer);
-               }
-
-               void SeekableStream::metadata_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       instance->metadata_callback(metadata);
-               }
-
-               void SeekableStream::error_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data)
-               {
-                       (void) decoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       instance->error_callback(status);
-               }
-
-       }
-}
diff --git a/src/libOggFLAC++/seekable_stream_encoder.cpp b/src/libOggFLAC++/seekable_stream_encoder.cpp
deleted file mode 100644 (file)
index e96bd16..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-/* libOggFLAC++ - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "OggFLAC++/encoder.h"
-#include "FLAC/assert.h"
-
-#ifdef _MSC_VER
-// warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
-#pragma warning ( disable : 4800 )
-#endif
-
-namespace OggFLAC {
-       namespace Encoder {
-
-               SeekableStream::SeekableStream():
-               encoder_(::OggFLAC__seekable_stream_encoder_new())
-               { }
-
-               SeekableStream::~SeekableStream()
-               {
-                       if(0 != encoder_) {
-                               ::OggFLAC__seekable_stream_encoder_finish(encoder_);
-                               ::OggFLAC__seekable_stream_encoder_delete(encoder_);
-                       }
-               }
-
-               bool SeekableStream::set_serial_number(long value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_serial_number(encoder_, value);
-               }
-
-               bool SeekableStream::is_valid() const
-               {
-                       return 0 != encoder_;
-               }
-
-               bool SeekableStream::set_verify(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_verify(encoder_, value);
-               }
-
-               bool SeekableStream::set_streamable_subset(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_streamable_subset(encoder_, value);
-               }
-
-               bool SeekableStream::set_do_mid_side_stereo(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder_, value);
-               }
-
-               bool SeekableStream::set_loose_mid_side_stereo(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder_, value);
-               }
-
-               bool SeekableStream::set_channels(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_channels(encoder_, value);
-               }
-
-               bool SeekableStream::set_bits_per_sample(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_bits_per_sample(encoder_, value);
-               }
-
-               bool SeekableStream::set_sample_rate(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_sample_rate(encoder_, value);
-               }
-
-               bool SeekableStream::set_blocksize(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_blocksize(encoder_, value);
-               }
-
-               bool SeekableStream::set_apodization(const char *specification)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_apodization(encoder_, specification);
-               }
-
-               bool SeekableStream::set_max_lpc_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_max_lpc_order(encoder_, value);
-               }
-
-               bool SeekableStream::set_qlp_coeff_precision(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder_, value);
-               }
-
-               bool SeekableStream::set_do_qlp_coeff_prec_search(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder_, value);
-               }
-
-               bool SeekableStream::set_do_escape_coding(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_do_escape_coding(encoder_, value);
-               }
-
-               bool SeekableStream::set_do_exhaustive_model_search(bool value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder_, value);
-               }
-
-               bool SeekableStream::set_min_residual_partition_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder_, value);
-               }
-
-               bool SeekableStream::set_max_residual_partition_order(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder_, value);
-               }
-
-               bool SeekableStream::set_rice_parameter_search_dist(unsigned value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder_, value);
-               }
-
-               bool SeekableStream::set_total_samples_estimate(FLAC__uint64 value)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_total_samples_estimate(encoder_, value);
-               }
-
-               bool SeekableStream::set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_set_metadata(encoder_, metadata, num_blocks);
-               }
-
-               SeekableStream::State SeekableStream::get_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return State(::OggFLAC__seekable_stream_encoder_get_state(encoder_));
-               }
-
-               FLAC::Encoder::Stream::State SeekableStream::get_FLAC_stream_encoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return FLAC::Encoder::Stream::State(::OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(encoder_));
-               }
-
-               FLAC::Decoder::Stream::State SeekableStream::get_verify_decoder_state() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return FLAC::Decoder::Stream::State(::OggFLAC__seekable_stream_encoder_get_verify_decoder_state(encoder_));
-               }
-
-               void SeekableStream::get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder_, absolute_sample, frame_number, channel, sample, expected, got);
-               }
-
-               bool SeekableStream::get_verify() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_get_verify(encoder_);
-               }
-
-               bool SeekableStream::get_streamable_subset() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_get_streamable_subset(encoder_);
-               }
-
-               bool SeekableStream::get_do_mid_side_stereo() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder_);
-               }
-
-               bool SeekableStream::get_loose_mid_side_stereo() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder_);
-               }
-
-               unsigned SeekableStream::get_channels() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_channels(encoder_);
-               }
-
-               unsigned SeekableStream::get_bits_per_sample() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_bits_per_sample(encoder_);
-               }
-
-               unsigned SeekableStream::get_sample_rate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_sample_rate(encoder_);
-               }
-
-               unsigned SeekableStream::get_blocksize() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_blocksize(encoder_);
-               }
-
-               unsigned SeekableStream::get_max_lpc_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_max_lpc_order(encoder_);
-               }
-
-               unsigned SeekableStream::get_qlp_coeff_precision() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder_);
-               }
-
-               bool SeekableStream::get_do_qlp_coeff_prec_search() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder_);
-               }
-
-               bool SeekableStream::get_do_escape_coding() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_get_do_escape_coding(encoder_);
-               }
-
-               bool SeekableStream::get_do_exhaustive_model_search() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder_);
-               }
-
-               unsigned SeekableStream::get_min_residual_partition_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder_);
-               }
-
-               unsigned SeekableStream::get_max_residual_partition_order() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder_);
-               }
-
-               unsigned SeekableStream::get_rice_parameter_search_dist() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder_);
-               }
-
-               FLAC__uint64 SeekableStream::get_total_samples_estimate() const
-               {
-                       FLAC__ASSERT(is_valid());
-                       return ::OggFLAC__seekable_stream_encoder_get_total_samples_estimate(encoder_);
-               }
-
-               SeekableStream::State SeekableStream::init()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::OggFLAC__seekable_stream_encoder_set_read_callback(encoder_, read_callback_);
-                       ::OggFLAC__seekable_stream_encoder_set_seek_callback(encoder_, seek_callback_);
-                       ::OggFLAC__seekable_stream_encoder_set_tell_callback(encoder_, tell_callback_);
-                       ::OggFLAC__seekable_stream_encoder_set_write_callback(encoder_, write_callback_);
-                       ::OggFLAC__seekable_stream_encoder_set_client_data(encoder_, (void*)this);
-                       return State(::OggFLAC__seekable_stream_encoder_init(encoder_));
-               }
-
-               void SeekableStream::finish()
-               {
-                       FLAC__ASSERT(is_valid());
-                       ::OggFLAC__seekable_stream_encoder_finish(encoder_);
-               }
-
-               bool SeekableStream::process(const FLAC__int32 * const buffer[], unsigned samples)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_process(encoder_, buffer, samples);
-               }
-
-               bool SeekableStream::process_interleaved(const FLAC__int32 buffer[], unsigned samples)
-               {
-                       FLAC__ASSERT(is_valid());
-                       return (bool)::OggFLAC__seekable_stream_encoder_process_interleaved(encoder_, buffer, samples);
-               }
-
-               ::OggFLAC__SeekableStreamEncoderReadStatus SeekableStream::read_callback_(const ::OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-               {
-                       (void)encoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->read_callback(buffer, bytes);
-               }
-
-               ::FLAC__SeekableStreamEncoderSeekStatus SeekableStream::seek_callback_(const ::OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-               {
-                       (void)encoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->seek_callback(absolute_byte_offset);
-               }
-
-               ::FLAC__SeekableStreamEncoderTellStatus SeekableStream::tell_callback_(const ::OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-               {
-                       (void)encoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->tell_callback(absolute_byte_offset);
-               }
-
-               ::FLAC__StreamEncoderWriteStatus SeekableStream::write_callback_(const ::OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-               {
-                       (void)encoder;
-                       FLAC__ASSERT(0 != client_data);
-                       SeekableStream *instance = reinterpret_cast<SeekableStream *>(client_data);
-                       FLAC__ASSERT(0 != instance);
-                       return instance->write_callback(buffer, bytes, samples, current_frame);
-               }
-
-       }
-}
index 42ab727..b2531ae 100644 (file)
@@ -57,6 +57,12 @@ namespace OggFLAC {
                        return 0 != decoder_;
                }
 
+               bool Stream::set_md5_checking(bool value)
+               {
+                       FLAC__ASSERT(is_valid());
+                       return (bool)::OggFLAC__stream_decoder_set_md5_checking(decoder_, value);
+               }
+
                bool Stream::set_serial_number(long value)
                {
                        FLAC__ASSERT(is_valid());
@@ -111,6 +117,18 @@ namespace OggFLAC {
                        return FLAC::Decoder::Stream::State(::OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder_));
                }
 
+               bool Stream::get_md5_checking() const
+               {
+                       FLAC__ASSERT(is_valid());
+                       return (bool)::OggFLAC__stream_decoder_get_md5_checking(decoder_);
+               }
+
+               FLAC__uint64 Stream::get_total_samples() const
+               {
+                       FLAC__ASSERT(is_valid());
+                       return ::OggFLAC__stream_decoder_get_total_samples(decoder_);
+               }
+
                unsigned Stream::get_channels() const
                {
                        FLAC__ASSERT(is_valid());
@@ -141,15 +159,10 @@ namespace OggFLAC {
                        return ::OggFLAC__stream_decoder_get_blocksize(decoder_);
                }
 
-               Stream::State Stream::init()
+               ::FLAC__StreamDecoderInitStatus Stream::init()
                {
                        FLAC__ASSERT(is_valid());
-                       ::OggFLAC__stream_decoder_set_read_callback(decoder_, read_callback_);
-                       ::OggFLAC__stream_decoder_set_write_callback(decoder_, write_callback_);
-                       ::OggFLAC__stream_decoder_set_metadata_callback(decoder_, metadata_callback_);
-                       ::OggFLAC__stream_decoder_set_error_callback(decoder_, error_callback_);
-                       ::OggFLAC__stream_decoder_set_client_data(decoder_, (void*)this);
-                       return State(::OggFLAC__stream_decoder_init(decoder_));
+                       return ::OggFLAC__stream_decoder_init_stream(decoder_, read_callback_, seek_callback_, tell_callback_, length_callback_, eof_callback_, write_callback_, metadata_callback_, error_callback_, /*client_data=*/(void*)this);
                }
 
                void Stream::finish()
@@ -188,7 +201,47 @@ namespace OggFLAC {
                        return (bool)::OggFLAC__stream_decoder_process_until_end_of_stream(decoder_);
                }
 
-               ::FLAC__StreamDecoderReadStatus Stream::read_callback_(const ::OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+               bool Stream::skip_single_frame()
+               {
+                       FLAC__ASSERT(is_valid());
+                       return (bool)::OggFLAC__stream_decoder_skip_single_frame(decoder_);
+               }
+
+               bool Stream::seek_absolute(FLAC__uint64 sample)
+               {
+                       FLAC__ASSERT(is_valid());
+                       return (bool)::OggFLAC__stream_decoder_seek_absolute(decoder_, sample);
+               }
+
+               ::FLAC__StreamDecoderSeekStatus Stream::seek_callback(FLAC__uint64 absolute_byte_offset)
+               {
+                       (void)absolute_byte_offset;
+                       return ::FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+               }
+
+               ::FLAC__StreamDecoderTellStatus Stream::tell_callback(FLAC__uint64 *absolute_byte_offset)
+               {
+                       (void)absolute_byte_offset;
+                       return ::FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
+               }
+
+               ::FLAC__StreamDecoderLengthStatus Stream::length_callback(FLAC__uint64 *stream_length)
+               {
+                       (void)stream_length;
+                       return ::FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+               }
+
+               bool Stream::eof_callback()
+               {
+                       return false;
+               }
+
+               void Stream::metadata_callback(const ::FLAC__StreamMetadata *metadata)
+               {
+                       (void)metadata;
+               }
+
+               ::FLAC__StreamDecoderReadStatus Stream::read_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
                {
                        (void)decoder;
                        FLAC__ASSERT(0 != client_data);
@@ -197,7 +250,43 @@ namespace OggFLAC {
                        return instance->read_callback(buffer, bytes);
                }
 
-               ::FLAC__StreamDecoderWriteStatus Stream::write_callback_(const ::OggFLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+               ::FLAC__StreamDecoderSeekStatus Stream::seek_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+               {
+                       (void) decoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->seek_callback(absolute_byte_offset);
+               }
+
+               ::FLAC__StreamDecoderTellStatus Stream::tell_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+               {
+                       (void) decoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->tell_callback(absolute_byte_offset);
+               }
+
+               ::FLAC__StreamDecoderLengthStatus Stream::length_callback_(const ::FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
+               {
+                       (void) decoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->length_callback(stream_length);
+               }
+
+               FLAC__bool Stream::eof_callback_(const ::FLAC__StreamDecoder *decoder, void *client_data)
+               {
+                       (void) decoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->eof_callback();
+               }
+
+               ::FLAC__StreamDecoderWriteStatus Stream::write_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
                {
                        (void)decoder;
                        FLAC__ASSERT(0 != client_data);
@@ -206,7 +295,7 @@ namespace OggFLAC {
                        return instance->write_callback(frame, buffer);
                }
 
-               void Stream::metadata_callback_(const ::OggFLAC__StreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
+               void Stream::metadata_callback_(const ::FLAC__StreamDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
                {
                        (void)decoder;
                        FLAC__ASSERT(0 != client_data);
@@ -215,7 +304,7 @@ namespace OggFLAC {
                        instance->metadata_callback(metadata);
                }
 
-               void Stream::error_callback_(const ::OggFLAC__StreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data)
+               void Stream::error_callback_(const ::FLAC__StreamDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data)
                {
                        (void)decoder;
                        FLAC__ASSERT(0 != client_data);
index 183cf55..e4281c3 100644 (file)
@@ -177,6 +177,31 @@ namespace OggFLAC {
                        return (bool)::OggFLAC__stream_encoder_set_metadata(encoder_, metadata, num_blocks);
                }
 
+               bool Stream::set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks)
+               {
+                       FLAC__ASSERT(is_valid());
+#if (defined _MSC_VER) || (defined __SUNPRO_CC)
+                       // MSVC++ can't handle:
+                       // ::FLAC__StreamMetadata *m[num_blocks];
+                       // so we do this ugly workaround
+                       ::FLAC__StreamMetadata **m = new ::FLAC__StreamMetadata*[num_blocks];
+#else
+                       ::FLAC__StreamMetadata *m[num_blocks];
+#endif
+                       for(unsigned i = 0; i < num_blocks; i++) {
+                               // we can get away with the const_cast since we know the encoder will only correct the is_last flags
+                               m[i] = const_cast< ::FLAC__StreamMetadata*>((const ::FLAC__StreamMetadata*)metadata[i]);
+                       }
+#if (defined _MSC_VER) || (defined __SUNPRO_CC)
+                       // complete the hack
+                       const bool ok = (bool)::OggFLAC__stream_encoder_set_metadata(encoder_, m, num_blocks);
+                       delete [] m;
+                       return ok;
+#else
+                       return (bool)::OggFLAC__stream_encoder_set_metadata(encoder_, m, num_blocks);
+#endif
+               }
+
                Stream::State Stream::get_state() const
                {
                        FLAC__ASSERT(is_valid());
@@ -303,13 +328,10 @@ namespace OggFLAC {
                        return ::OggFLAC__stream_encoder_get_total_samples_estimate(encoder_);
                }
 
-               Stream::State Stream::init()
+               ::FLAC__StreamEncoderInitStatus Stream::init()
                {
                        FLAC__ASSERT(is_valid());
-                       ::OggFLAC__stream_encoder_set_write_callback(encoder_, write_callback_);
-                       ::OggFLAC__stream_encoder_set_metadata_callback(encoder_, metadata_callback_);
-                       ::OggFLAC__stream_encoder_set_client_data(encoder_, (void*)this);
-                       return State(::OggFLAC__stream_encoder_init(encoder_));
+                       return ::OggFLAC__stream_encoder_init_stream(encoder_, read_callback_, write_callback_, seek_callback_, tell_callback_, metadata_callback_, /*client_data=*/(void*)this);
                }
 
                void Stream::finish()
@@ -330,7 +352,39 @@ namespace OggFLAC {
                        return (bool)::OggFLAC__stream_encoder_process_interleaved(encoder_, buffer, samples);
                }
 
-               ::FLAC__StreamEncoderWriteStatus Stream::write_callback_(const ::OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
+               ::OggFLAC__StreamEncoderReadStatus Stream::read_callback(FLAC__byte buffer[], unsigned *bytes)
+               {
+                       (void)buffer, (void)bytes;
+                       return ::OggFLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED;
+               }
+
+               ::FLAC__StreamEncoderSeekStatus Stream::seek_callback(FLAC__uint64 absolute_byte_offset)
+               {
+                       (void)absolute_byte_offset;
+                       return ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
+               }
+
+               ::FLAC__StreamEncoderTellStatus Stream::tell_callback(FLAC__uint64 *absolute_byte_offset)
+               {
+                       (void)absolute_byte_offset;
+                       return ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
+               }
+
+               void Stream::metadata_callback(const ::FLAC__StreamMetadata *metadata)
+               {
+                       (void)metadata;
+               }
+
+               ::OggFLAC__StreamEncoderReadStatus Stream::read_callback_(const ::OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+               {
+                       (void)encoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->read_callback(buffer, bytes);
+               }
+
+               ::FLAC__StreamEncoderWriteStatus Stream::write_callback_(const ::FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
                {
                        (void)encoder;
                        FLAC__ASSERT(0 != client_data);
@@ -339,7 +393,25 @@ namespace OggFLAC {
                        return instance->write_callback(buffer, bytes, samples, current_frame);
                }
 
-               void Stream::metadata_callback_(const ::OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
+               ::FLAC__StreamEncoderSeekStatus Stream::seek_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+               {
+                       (void)encoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->seek_callback(absolute_byte_offset);
+               }
+
+               ::FLAC__StreamEncoderTellStatus Stream::tell_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+               {
+                       (void)encoder;
+                       FLAC__ASSERT(0 != client_data);
+                       Stream *instance = reinterpret_cast<Stream *>(client_data);
+                       FLAC__ASSERT(0 != instance);
+                       return instance->tell_callback(absolute_byte_offset);
+               }
+
+               void Stream::metadata_callback_(const ::FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
                {
                        (void)encoder;
                        FLAC__ASSERT(0 != client_data);
index aa4eaf3..7b198eb 100644 (file)
@@ -51,13 +51,9 @@ libOggFLAC_la_LIBADD = @OGG_LIBS@ ../libFLAC/libFLAC.la
 libOggFLAC_la_LDFLAGS = -version-info 3:0:0
 
 libOggFLAC_la_SOURCES = \
-       file_decoder.c \
-       file_encoder.c \
        ogg_decoder_aspect.c \
        ogg_encoder_aspect.c \
        ogg_helper.c \
        ogg_mapping.c \
-       seekable_stream_decoder.c \
-       seekable_stream_encoder.c \
        stream_decoder.c \
        stream_encoder.c
index 9144a22..1f10aed 100644 (file)
@@ -48,14 +48,10 @@ INCLUDES = -I./include -I$(topdir)/include -I$(OGG_INCLUDE_DIR)
 DEBUG_CFLAGS = 
 
 SRCS_C = \
-       file_decoder.c \
-       file_encoder.c \
        ogg_decoder_aspect.c \
        ogg_encoder_aspect.c \
        ogg_helper.c \
        ogg_mapping.c \
-       seekable_stream_decoder.c \
-       seekable_stream_encoder.c \
        stream_decoder.c \
        stream_encoder.c
 
diff --git a/src/libOggFLAC/file_decoder.c b/src/libOggFLAC/file_decoder.c
deleted file mode 100644 (file)
index 926f6bc..0000000
+++ /dev/null
@@ -1,672 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for strcmp() */
-#include <sys/stat.h> /* for stat() */
-#if defined _MSC_VER || defined __MINGW32__
-#include <io.h> /* for _setmode() */
-#include <fcntl.h> /* for _O_BINARY */
-#include <sys/types.h> /* for off_t */
-//@@@ [2G limit] hacks for MSVC6
-#define fseeko fseek
-#define ftello ftell
-#elif defined __CYGWIN__
-#include <io.h> /* for setmode(), O_BINARY */
-#include <fcntl.h> /* for _O_BINARY */
-#endif
-#include "FLAC/assert.h"
-#include "protected/file_decoder.h"
-#include "protected/seekable_stream_decoder.h"
-
-/***********************************************************************
- *
- * Private class method prototypes
- *
- ***********************************************************************/
-
-static void set_defaults_(OggFLAC__FileDecoder *decoder);
-static FILE *get_binary_stdin_();
-static OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-static OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-static OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-static OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
-static FLAC__bool eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data);
-static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-static void metadata_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void error_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-
-/***********************************************************************
- *
- * Private class data
- *
- ***********************************************************************/
-
-typedef struct OggFLAC__FileDecoderPrivate {
-       OggFLAC__FileDecoderWriteCallback write_callback;
-       OggFLAC__FileDecoderMetadataCallback metadata_callback;
-       OggFLAC__FileDecoderErrorCallback error_callback;
-       void *client_data;
-       FILE *file;
-       char *filename; /* == NULL if stdin */
-       OggFLAC__SeekableStreamDecoder *seekable_stream_decoder;
-} OggFLAC__FileDecoderPrivate;
-
-/***********************************************************************
- *
- * Public static class data
- *
- ***********************************************************************/
-
-OggFLAC_API const char * const OggFLAC__FileDecoderStateString[] = {
-       "OggFLAC__FILE_DECODER_OK",
-       "OggFLAC__FILE_DECODER_END_OF_FILE",
-       "OggFLAC__FILE_DECODER_ERROR_OPENING_FILE",
-       "OggFLAC__FILE_DECODER_SEEK_ERROR",
-       "OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR",
-       "OggFLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR",
-       "OggFLAC__FILE_DECODER_ALREADY_INITIALIZED",
-       "OggFLAC__FILE_DECODER_INVALID_CALLBACK",
-       "OggFLAC__FILE_DECODER_UNINITIALIZED"
-};
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-OggFLAC_API OggFLAC__FileDecoder *OggFLAC__file_decoder_new()
-{
-       OggFLAC__FileDecoder *decoder;
-
-       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
-
-       decoder = (OggFLAC__FileDecoder*)calloc(1, sizeof(OggFLAC__FileDecoder));
-       if(decoder == 0) {
-               return 0;
-       }
-
-       decoder->protected_ = (OggFLAC__FileDecoderProtected*)calloc(1, sizeof(OggFLAC__FileDecoderProtected));
-       if(decoder->protected_ == 0) {
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_ = (OggFLAC__FileDecoderPrivate*)calloc(1, sizeof(OggFLAC__FileDecoderPrivate));
-       if(decoder->private_ == 0) {
-               free(decoder->protected_);
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_->seekable_stream_decoder = OggFLAC__seekable_stream_decoder_new();
-       if(0 == decoder->private_->seekable_stream_decoder) {
-               free(decoder->private_);
-               free(decoder->protected_);
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_->file = 0;
-
-       set_defaults_(decoder);
-
-       decoder->protected_->state = OggFLAC__FILE_DECODER_UNINITIALIZED;
-
-       return decoder;
-}
-
-OggFLAC_API void OggFLAC__file_decoder_delete(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-
-       (void)OggFLAC__file_decoder_finish(decoder);
-
-       OggFLAC__seekable_stream_decoder_delete(decoder->private_->seekable_stream_decoder);
-
-       free(decoder->private_);
-       free(decoder->protected_);
-       free(decoder);
-}
-
-/***********************************************************************
- *
- * Public class methods
- *
- ***********************************************************************/
-
-OggFLAC_API OggFLAC__FileDecoderState OggFLAC__file_decoder_init(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return decoder->protected_->state = OggFLAC__FILE_DECODER_ALREADY_INITIALIZED;
-
-       if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
-               return decoder->protected_->state = OggFLAC__FILE_DECODER_INVALID_CALLBACK;
-
-       if(0 == decoder->private_->filename)
-               decoder->private_->file = get_binary_stdin_();
-       else
-               decoder->private_->file = fopen(decoder->private_->filename, "rb");
-
-       if(decoder->private_->file == 0)
-               return decoder->protected_->state = OggFLAC__FILE_DECODER_ERROR_OPENING_FILE;
-
-       OggFLAC__seekable_stream_decoder_set_read_callback(decoder->private_->seekable_stream_decoder, read_callback_);
-       OggFLAC__seekable_stream_decoder_set_seek_callback(decoder->private_->seekable_stream_decoder, seek_callback_);
-       OggFLAC__seekable_stream_decoder_set_tell_callback(decoder->private_->seekable_stream_decoder, tell_callback_);
-       OggFLAC__seekable_stream_decoder_set_length_callback(decoder->private_->seekable_stream_decoder, length_callback_);
-       OggFLAC__seekable_stream_decoder_set_eof_callback(decoder->private_->seekable_stream_decoder, eof_callback_);
-       OggFLAC__seekable_stream_decoder_set_write_callback(decoder->private_->seekable_stream_decoder, write_callback_);
-       OggFLAC__seekable_stream_decoder_set_metadata_callback(decoder->private_->seekable_stream_decoder, metadata_callback_);
-       OggFLAC__seekable_stream_decoder_set_error_callback(decoder->private_->seekable_stream_decoder, error_callback_);
-       OggFLAC__seekable_stream_decoder_set_client_data(decoder->private_->seekable_stream_decoder, decoder);
-
-       if(OggFLAC__seekable_stream_decoder_init(decoder->private_->seekable_stream_decoder) != OggFLAC__SEEKABLE_STREAM_DECODER_OK)
-               return decoder->protected_->state = OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return decoder->protected_->state = OggFLAC__FILE_DECODER_OK;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_finish(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->protected_->state == OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return true;
-
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-
-       if(0 != decoder->private_->file && decoder->private_->file != stdin) {
-               fclose(decoder->private_->file);
-               decoder->private_->file = 0;
-       }
-
-       if(0 != decoder->private_->filename) {
-               free(decoder->private_->filename);
-               decoder->private_->filename = 0;
-       }
-
-       set_defaults_(decoder);
-
-       decoder->protected_->state = OggFLAC__FILE_DECODER_UNINITIALIZED;
-
-       return OggFLAC__seekable_stream_decoder_finish(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_md5_checking(OggFLAC__FileDecoder *decoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_decoder_set_md5_checking(decoder->private_->seekable_stream_decoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_filename(OggFLAC__FileDecoder *decoder, const char *value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       if(0 != decoder->private_->filename) {
-               free(decoder->private_->filename);
-               decoder->private_->filename = 0;
-       }
-       if(0 != strcmp(value, "-")) {
-               if(0 == (decoder->private_->filename = (char*)malloc(strlen(value)+1))) {
-                       decoder->protected_->state = OggFLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR;
-                       return false;
-               }
-               strcpy(decoder->private_->filename, value);
-       }
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_write_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->write_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderMetadataCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->metadata_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_error_callback(OggFLAC__FileDecoder *decoder, OggFLAC__FileDecoderErrorCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->error_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_client_data(OggFLAC__FileDecoder *decoder, void *value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->client_data = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_serial_number(OggFLAC__FileDecoder *decoder, long value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       OggFLAC__seekable_stream_decoder_set_serial_number(decoder->private_->seekable_stream_decoder, value);
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond(OggFLAC__FileDecoder *decoder, FLAC__MetadataType type)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder->private_->seekable_stream_decoder, type);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond_application(OggFLAC__FileDecoder *decoder, const FLAC__byte id[4])
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_decoder_set_metadata_respond_application(decoder->private_->seekable_stream_decoder, id);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_respond_all(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore(OggFLAC__FileDecoder *decoder, FLAC__MetadataType type)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_decoder_set_metadata_ignore(decoder->private_->seekable_stream_decoder, type);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore_application(OggFLAC__FileDecoder *decoder, const FLAC__byte id[4])
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder->private_->seekable_stream_decoder, id);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_set_metadata_ignore_all(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API OggFLAC__FileDecoderState OggFLAC__file_decoder_get_state(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       return decoder->protected_->state;
-}
-
-OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__file_decoder_get_seekable_stream_decoder_state(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_state(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__file_decoder_get_stream_decoder_state(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_stream_decoder_state(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_decoder_get_FLAC_stream_decoder_state(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API const char *OggFLAC__file_decoder_get_resolved_state_string(const OggFLAC__FileDecoder *decoder)
-{
-       if(decoder->protected_->state != OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR)
-               return OggFLAC__FileDecoderStateString[decoder->protected_->state];
-       else
-               return OggFLAC__seekable_stream_decoder_get_resolved_state_string(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_get_md5_checking(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_md5_checking(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_decoder_get_channels(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_channels(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API FLAC__ChannelAssignment OggFLAC__file_decoder_get_channel_assignment(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_channel_assignment(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_decoder_get_bits_per_sample(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_bits_per_sample(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_decoder_get_sample_rate(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_sample_rate(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_decoder_get_blocksize(const OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__seekable_stream_decoder_get_blocksize(decoder->private_->seekable_stream_decoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_single(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = OggFLAC__FILE_DECODER_END_OF_FILE;
-
-       if(decoder->protected_->state == OggFLAC__FILE_DECODER_END_OF_FILE)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == OggFLAC__FILE_DECODER_OK);
-
-       ret = OggFLAC__seekable_stream_decoder_process_single(decoder->private_->seekable_stream_decoder);
-       if(!ret)
-               decoder->protected_->state = OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_metadata(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = OggFLAC__FILE_DECODER_END_OF_FILE;
-
-       if(decoder->protected_->state == OggFLAC__FILE_DECODER_END_OF_FILE)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == OggFLAC__FILE_DECODER_OK);
-
-       ret = OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder->private_->seekable_stream_decoder);
-       if(!ret)
-               decoder->protected_->state = OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_process_until_end_of_file(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = OggFLAC__FILE_DECODER_END_OF_FILE;
-
-       if(decoder->protected_->state == OggFLAC__FILE_DECODER_END_OF_FILE)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == OggFLAC__FILE_DECODER_OK);
-
-       ret = OggFLAC__seekable_stream_decoder_process_until_end_of_stream(decoder->private_->seekable_stream_decoder);
-       if(!ret)
-               decoder->protected_->state = OggFLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_decoder_seek_absolute(OggFLAC__FileDecoder *decoder, FLAC__uint64 sample)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(decoder->protected_->state == OggFLAC__FILE_DECODER_OK || decoder->protected_->state == OggFLAC__FILE_DECODER_END_OF_FILE);
-
-       if(decoder->private_->filename == 0) { /* means the file is stdin... */
-               decoder->protected_->state = OggFLAC__FILE_DECODER_SEEK_ERROR;
-               return false;
-       }
-
-       if(!OggFLAC__seekable_stream_decoder_seek_absolute(decoder->private_->seekable_stream_decoder, sample)) {
-               decoder->protected_->state = OggFLAC__FILE_DECODER_SEEK_ERROR;
-               return false;
-       }
-       else {
-               decoder->protected_->state = OggFLAC__FILE_DECODER_OK;
-               return true;
-       }
-}
-
-
-/***********************************************************************
- *
- * Private class methods
- *
- ***********************************************************************/
-
-void set_defaults_(OggFLAC__FileDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-
-       decoder->private_->filename = 0;
-       decoder->private_->write_callback = 0;
-       decoder->private_->metadata_callback = 0;
-       decoder->private_->error_callback = 0;
-       decoder->private_->client_data = 0;
-}
-
-/*
- * This will forcibly set stdin to binary mode (for OSes that require it)
- */
-FILE *get_binary_stdin_()
-{
-       /* if something breaks here it is probably due to the presence or
-        * absence of an underscore before the identifiers 'setmode',
-        * 'fileno', and/or 'O_BINARY'; check your system header files.
-        */
-#if defined _MSC_VER || defined __MINGW32__
-       _setmode(_fileno(stdin), _O_BINARY);
-#elif defined __CYGWIN__
-       /* almost certainly not needed for any modern Cygwin, but let's be safe... */
-       setmode(_fileno(stdin), _O_BINARY);
-#endif
-
-       return stdin;
-}
-
-OggFLAC__SeekableStreamDecoderReadStatus read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-{
-       OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       if(*bytes > 0) {
-               *bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, file_decoder->private_->file);
-               if(ferror(file_decoder->private_->file)) {
-                       return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-               }
-               else {
-                       return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-               }
-       }
-       else
-               return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
-}
-
-OggFLAC__SeekableStreamDecoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-{
-       OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       if(fseeko(file_decoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
-               return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-       else
-               return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-OggFLAC__SeekableStreamDecoderTellStatus tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-{
-       OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
-       off_t pos;
-       (void)decoder;
-
-       if((pos = ftello(file_decoder->private_->file)) < 0)
-               return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-       else {
-               *absolute_byte_offset = (FLAC__uint64)pos;
-               return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
-       }
-}
-
-OggFLAC__SeekableStreamDecoderLengthStatus length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
-{
-       OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
-       struct stat filestats;
-       (void)decoder;
-
-       if(0 == file_decoder->private_->filename || stat(file_decoder->private_->filename, &filestats) != 0)
-               return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
-       else {
-               *stream_length = (FLAC__uint64)filestats.st_size;
-               return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
-       }
-}
-
-FLAC__bool eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data)
-{
-       OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       return feof(file_decoder->private_->file)? true : false;
-}
-
-FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       return file_decoder->private_->write_callback(file_decoder, frame, buffer, file_decoder->private_->client_data);
-}
-
-void metadata_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       file_decoder->private_->metadata_callback(file_decoder, metadata, file_decoder->private_->client_data);
-}
-
-void error_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       OggFLAC__FileDecoder *file_decoder = (OggFLAC__FileDecoder *)client_data;
-       (void)decoder;
-
-       file_decoder->private_->error_callback(file_decoder, status, file_decoder->private_->client_data);
-}
diff --git a/src/libOggFLAC/file_encoder.c b/src/libOggFLAC/file_encoder.c
deleted file mode 100644 (file)
index e9e2821..0000000
+++ /dev/null
@@ -1,835 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for strlen(), strcpy() */
-#if defined _MSC_VER || defined __MINGW32__
-#include <sys/types.h> /* for off_t */
-//@@@ [2G limit] hacks for MSVC6
-#define fseeko fseek
-#define ftello ftell
-#endif
-#include "FLAC/assert.h"
-#include "OggFLAC/seekable_stream_encoder.h"
-#include "protected/file_encoder.h"
-
-#ifdef max
-#undef max
-#endif
-#define max(x,y) ((x)>(y)?(x):(y))
-
-/***********************************************************************
- *
- * Private class method prototypes
- *
- ***********************************************************************/
-
-/* unpublished debug routines */
-extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_constant_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_fixed_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
-
-static void set_defaults_(OggFLAC__FileEncoder *encoder);
-static OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-static FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
-static FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
-static FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-
-/***********************************************************************
- *
- * Private class data
- *
- ***********************************************************************/
-
-typedef struct OggFLAC__FileEncoderPrivate {
-       OggFLAC__FileEncoderProgressCallback progress_callback;
-       void *client_data;
-       char *filename;
-       FLAC__uint64 bytes_written;
-       FLAC__uint64 samples_written;
-       unsigned frames_written;
-       unsigned total_frames_estimate;
-       OggFLAC__SeekableStreamEncoder *seekable_stream_encoder;
-       FILE *file;
-} OggFLAC__FileEncoderPrivate;
-
-/***********************************************************************
- *
- * Public static class data
- *
- ***********************************************************************/
-
-OggFLAC_API const char * const OggFLAC__FileEncoderStateString[] = {
-       "OggFLAC__FILE_ENCODER_OK",
-       "OggFLAC__FILE_ENCODER_NO_FILENAME",
-       "OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR",
-       "OggFLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING",
-       "OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE",
-       "OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR",
-       "OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED",
-       "OggFLAC__FILE_ENCODER_UNINITIALIZED"
-};
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-OggFLAC_API OggFLAC__FileEncoder *OggFLAC__file_encoder_new()
-{
-       OggFLAC__FileEncoder *encoder;
-
-       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
-
-       encoder = (OggFLAC__FileEncoder*)calloc(1, sizeof(OggFLAC__FileEncoder));
-       if(encoder == 0) {
-               return 0;
-       }
-
-       encoder->protected_ = (OggFLAC__FileEncoderProtected*)calloc(1, sizeof(OggFLAC__FileEncoderProtected));
-       if(encoder->protected_ == 0) {
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_ = (OggFLAC__FileEncoderPrivate*)calloc(1, sizeof(OggFLAC__FileEncoderPrivate));
-       if(encoder->private_ == 0) {
-               free(encoder->protected_);
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_->seekable_stream_encoder = OggFLAC__seekable_stream_encoder_new();
-       if(0 == encoder->private_->seekable_stream_encoder) {
-               free(encoder->private_);
-               free(encoder->protected_);
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_->file = 0;
-
-       set_defaults_(encoder);
-
-       encoder->protected_->state = OggFLAC__FILE_ENCODER_UNINITIALIZED;
-
-       return encoder;
-}
-
-OggFLAC_API void OggFLAC__file_encoder_delete(OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-
-       (void)OggFLAC__file_encoder_finish(encoder);
-
-       OggFLAC__seekable_stream_encoder_delete(encoder->private_->seekable_stream_encoder);
-
-       free(encoder->private_);
-       free(encoder->protected_);
-       free(encoder);
-}
-
-/***********************************************************************
- *
- * Public class methods
- *
- ***********************************************************************/
-
-OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_init(OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return encoder->protected_->state = OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED;
-
-       if(0 == encoder->private_->filename)
-               return encoder->protected_->state = OggFLAC__FILE_ENCODER_NO_FILENAME;
-
-       encoder->private_->file = fopen(encoder->private_->filename, "w+b");
-
-       if(encoder->private_->file == 0)
-               return encoder->protected_->state = OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE;
-
-       encoder->private_->bytes_written = 0;
-       encoder->private_->samples_written = 0;
-       encoder->private_->frames_written = 0;
-
-       OggFLAC__seekable_stream_encoder_set_read_callback(encoder->private_->seekable_stream_encoder, read_callback_);
-       OggFLAC__seekable_stream_encoder_set_seek_callback(encoder->private_->seekable_stream_encoder, seek_callback_);
-       OggFLAC__seekable_stream_encoder_set_tell_callback(encoder->private_->seekable_stream_encoder, tell_callback_);
-       OggFLAC__seekable_stream_encoder_set_write_callback(encoder->private_->seekable_stream_encoder, write_callback_);
-       OggFLAC__seekable_stream_encoder_set_client_data(encoder->private_->seekable_stream_encoder, encoder);
-
-       if(OggFLAC__seekable_stream_encoder_init(encoder->private_->seekable_stream_encoder) != OggFLAC__SEEKABLE_STREAM_ENCODER_OK)
-               return encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
-
-       {
-               unsigned blocksize = OggFLAC__file_encoder_get_blocksize(encoder);
-
-               FLAC__ASSERT(blocksize != 0);
-               encoder->private_->total_frames_estimate = (unsigned)((OggFLAC__file_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize);
-       }
-
-       return encoder->protected_->state = OggFLAC__FILE_ENCODER_OK;
-}
-
-OggFLAC_API void OggFLAC__file_encoder_finish(OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-
-       if(encoder->protected_->state == OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return;
-
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-
-       /* OggFLAC__seekable_stream_encoder_finish() might write data so we must close the file after it. */
-
-       OggFLAC__seekable_stream_encoder_finish(encoder->private_->seekable_stream_encoder);
-
-       if(0 != encoder->private_->file) {
-               fclose(encoder->private_->file);
-               encoder->private_->file = 0;
-       }
-
-       if(0 != encoder->private_->filename) {
-               free(encoder->private_->filename);
-               encoder->private_->filename = 0;
-       }
-
-       set_defaults_(encoder);
-
-       encoder->protected_->state = OggFLAC__FILE_ENCODER_UNINITIALIZED;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_serial_number(OggFLAC__FileEncoder *encoder, long serial_number)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_serial_number(encoder->private_->seekable_stream_encoder, serial_number);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_verify(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_verify(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_streamable_subset(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_streamable_subset(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_loose_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_channels(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_channels(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_bits_per_sample(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_bits_per_sample(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_sample_rate(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_sample_rate(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_blocksize(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_blocksize(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_apodization(OggFLAC__FileEncoder *encoder, const char *specification)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_apodization(encoder->private_->seekable_stream_encoder, specification);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_lpc_order(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_max_lpc_order(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_qlp_coeff_precision(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_escape_coding(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_do_escape_coding(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_exhaustive_model_search(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_min_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_rice_parameter_search_dist(OggFLAC__FileEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_total_samples_estimate(OggFLAC__FileEncoder *encoder, FLAC__uint64 value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_total_samples_estimate(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_metadata(OggFLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_set_metadata(encoder->private_->seekable_stream_encoder, metadata, num_blocks);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_filename(OggFLAC__FileEncoder *encoder, const char *value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       if(0 != encoder->private_->filename) {
-               free(encoder->private_->filename);
-               encoder->private_->filename = 0;
-       }
-       if(0 == (encoder->private_->filename = (char*)malloc(strlen(value)+1))) {
-               encoder->protected_->state = OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR;
-               return false;
-       }
-       strcpy(encoder->private_->filename, value);
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_progress_callback(OggFLAC__FileEncoder *encoder, OggFLAC__FileEncoderProgressCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->progress_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_client_data(OggFLAC__FileEncoder *encoder, void *value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->client_data = value;
-       return true;
-}
-
-/*
- * These three functions are not static, but not publically exposed in
- * include/OggFLAC/ either.  They are used by the test suite.
- */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_constant_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_disable_constant_subframes(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_fixed_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_disable_fixed_subframes(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_verbatim_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(encoder->private_->seekable_stream_encoder, value);
-}
-
-OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_get_state(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->protected_);
-       return encoder->protected_->state;
-}
-
-OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__file_encoder_get_seekable_stream_encoder_state(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_state(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__StreamEncoderState OggFLAC__file_encoder_get_FLAC_stream_encoder_state(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_encoder_get_verify_decoder_state(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_verify_decoder_state(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API const char *OggFLAC__file_encoder_get_resolved_state_string(const OggFLAC__FileEncoder *encoder)
-{
-       if(encoder->protected_->state != OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR)
-               return OggFLAC__FileEncoderStateString[encoder->protected_->state];
-       else
-               return OggFLAC__seekable_stream_encoder_get_resolved_state_string(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API void OggFLAC__file_encoder_get_verify_decoder_error_stats(const OggFLAC__FileEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder->private_->seekable_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_verify(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_verify(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_streamable_subset(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_streamable_subset(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_mid_side_stereo(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_loose_mid_side_stereo(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_channels(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_channels(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_bits_per_sample(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_bits_per_sample(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_sample_rate(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_sample_rate(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_blocksize(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_blocksize(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_max_lpc_order(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_max_lpc_order(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_qlp_coeff_precision(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_escape_coding(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_do_escape_coding(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_exhaustive_model_search(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_min_residual_partition_order(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_max_residual_partition_order(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__file_encoder_get_rice_parameter_search_dist(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__uint64 OggFLAC__file_encoder_get_total_samples_estimate(const OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       return OggFLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->seekable_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_process(OggFLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       if(!OggFLAC__seekable_stream_encoder_process(encoder->private_->seekable_stream_encoder, buffer, samples)) {
-               encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
-               return false;
-       }
-       else
-               return true;
-}
-
-/* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
-OggFLAC_API FLAC__bool OggFLAC__file_encoder_process_interleaved(OggFLAC__FileEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       if(!OggFLAC__seekable_stream_encoder_process_interleaved(encoder->private_->seekable_stream_encoder, buffer, samples)) {
-               encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
-               return false;
-       }
-       else
-               return true;
-}
-
-
-/***********************************************************************
- *
- * Private class methods
- *
- ***********************************************************************/
-
-void set_defaults_(OggFLAC__FileEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-
-       encoder->private_->progress_callback = 0;
-       encoder->private_->client_data = 0;
-       encoder->private_->total_frames_estimate = 0;
-       encoder->private_->filename = 0;
-}
-
-OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-{
-       OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
-
-       (void)encoder;
-
-       FLAC__ASSERT(0 != file_encoder);
-
-       *bytes = (unsigned)fread(buffer, 1, *bytes, file_encoder->private_->file);
-       if (*bytes == 0) {
-               if (feof(file_encoder->private_->file))
-                       return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM;
-               else if (ferror(file_encoder->private_->file))
-                       return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT;
-       }
-       return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE;
-}
-
-FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-{
-       OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
-
-       (void)encoder;
-
-       FLAC__ASSERT(0 != file_encoder);
-
-       if(fseeko(file_encoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
-               return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR;
-       else
-               return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
-}
-
-FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-{
-       OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
-       off_t offset;
-
-       (void)encoder;
-
-       FLAC__ASSERT(0 != file_encoder);
-
-       offset = ftello(file_encoder->private_->file);
-
-       if(offset < 0) {
-               return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_ERROR;
-       }
-       else {
-               *absolute_byte_offset = (FLAC__uint64)offset;
-               return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK;
-       }
-}
-
-#ifdef FLAC__VALGRIND_TESTING
-static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
-       size_t ret = fwrite(ptr, size, nmemb, stream);
-       if(!ferror(stream))
-               fflush(stream);
-       return ret;
-}
-#else
-#define local__fwrite fwrite
-#endif
-
-FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
-
-       (void)encoder;
-
-       FLAC__ASSERT(0 != file_encoder);
-
-       if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, file_encoder->private_->file) == bytes) {
-               file_encoder->private_->bytes_written += bytes;
-               file_encoder->private_->samples_written += samples;
-               /* we keep a high watermark on the number of frames written
-                * because when the encoder goes back to write metadata,
-                * 'current_frame' will drop back to 0.
-                */
-               file_encoder->private_->frames_written = max(file_encoder->private_->frames_written, current_frame+1);
-               /*@@@ We would like to add an '&& samples > 0' to the if
-                * clause here but currently because of the nature of our Ogg
-                * writing implementation, 'samples' is always 0 (see
-                * ogg_encoder_aspect.c).  The downside is extra progress
-                * callbacks.
-                */
-               if(0 != file_encoder->private_->progress_callback)
-                       file_encoder->private_->progress_callback(file_encoder, file_encoder->private_->bytes_written, file_encoder->private_->samples_written, file_encoder->private_->frames_written, file_encoder->private_->total_frames_estimate, file_encoder->private_->client_data);
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-       }
-       else
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
-}
index fab57d9..ba5c3d2 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "FLAC/ordinals.h"
 #include "FLAC/stream_decoder.h" /* for FLAC__StreamDecoderReadStatus */
+#include "OggFLAC/stream_decoder.h"
 
 typedef struct OggFLAC__OggDecoderAspect {
        /* these are storage for values that can be set through the API */
@@ -74,6 +75,6 @@ typedef enum {
 
 typedef OggFLAC__OggDecoderAspectReadStatus (*OggFLAC__OggDecoderAspectReadCallbackProxy)(const void *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
 
-OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, void *decoder, void *client_data);
+OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, const OggFLAC__StreamDecoder *decoder, void *client_data);
 
 #endif
index 49f3096..5a0cfaf 100644 (file)
 #define OggFLAC__PRIVATE__OGG_HELPER_H
 
 #include <ogg/ogg.h>
-#include "OggFLAC/seekable_stream_encoder.h" /* for OggFLAC__SeekableStreamEncoder */
+#include "OggFLAC/stream_encoder.h" /* for OggFLAC__StreamEncoder */
 
 void simple_ogg_page__init(ogg_page *page);
 void simple_ogg_page__clear(ogg_page *page);
-FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data);
-FLAC__bool simple_ogg_page__set_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderWriteCallback write_callback, void *client_data);
+FLAC__bool simple_ogg_page__get_at(OggFLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, OggFLAC__StreamEncoderReadCallback read_callback, void *client_data);
+FLAC__bool simple_ogg_page__set_at(OggFLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data);
 
 #endif
index 552461d..fd7b6f9 100644 (file)
@@ -30,9 +30,5 @@
 
 noinst_HEADERS = \
        all.h \
-       file_decoder.h \
-       file_encoder.h \
-       seekable_stream_decoder.h \
-       seekable_stream_encoder.h \
        stream_decoder.h \
        stream_encoder.h
index ebbb270..3594079 100644 (file)
 #ifndef OggFLAC__PROTECTED__ALL_H
 #define OggFLAC__PROTECTED__ALL_H
 
-#include "file_decoder.h"
-#include "file_encoder.h"
-#include "seekable_stream_decoder.h"
-#include "seekable_stream_encoder.h"
 #include "stream_decoder.h"
 #include "stream_encoder.h"
 
diff --git a/src/libOggFLAC/include/protected/file_decoder.h b/src/libOggFLAC/include/protected/file_decoder.h
deleted file mode 100644 (file)
index ba130a1..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef OggFLAC__PROTECTED__FILE_DECODER_H
-#define OggFLAC__PROTECTED__FILE_DECODER_H
-
-#include "OggFLAC/file_decoder.h"
-
-typedef struct OggFLAC__FileDecoderProtected {
-       OggFLAC__FileDecoderState state;
-} OggFLAC__FileDecoderProtected;
-
-#endif
diff --git a/src/libOggFLAC/include/protected/file_encoder.h b/src/libOggFLAC/include/protected/file_encoder.h
deleted file mode 100644 (file)
index 0d850fd..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef OggFLAC__PROTECTED__FILE_ENCODER_H
-#define OggFLAC__PROTECTED__FILE_ENCODER_H
-
-#include "OggFLAC/file_encoder.h"
-
-typedef struct OggFLAC__FileEncoderProtected {
-       OggFLAC__FileEncoderState state;
-} OggFLAC__FileEncoderProtected;
-
-#endif
diff --git a/src/libOggFLAC/include/protected/seekable_stream_decoder.h b/src/libOggFLAC/include/protected/seekable_stream_decoder.h
deleted file mode 100644 (file)
index 9239323..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef OggFLAC__PROTECTED__SEEKABLE_STREAM_DECODER_H
-#define OggFLAC__PROTECTED__SEEKABLE_STREAM_DECODER_H
-
-#include "OggFLAC/seekable_stream_decoder.h"
-
-typedef struct OggFLAC__SeekableStreamDecoderProtected {
-       FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */
-       OggFLAC__SeekableStreamDecoderState state;
-} OggFLAC__SeekableStreamDecoderProtected;
-
-#endif
diff --git a/src/libOggFLAC/include/protected/seekable_stream_encoder.h b/src/libOggFLAC/include/protected/seekable_stream_encoder.h
deleted file mode 100644 (file)
index 0f2f3b9..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef OggFLAC__PROTECTED__SEEKABLE_STREAM_ENCODER_H
-#define OggFLAC__PROTECTED__SEEKABLE_STREAM_ENCODER_H
-
-#include "OggFLAC/seekable_stream_encoder.h"
-#include "private/ogg_encoder_aspect.h"
-
-typedef struct OggFLAC__SeekableStreamEncoderProtected {
-       OggFLAC__SeekableStreamEncoderState state;
-       OggFLAC__OggEncoderAspect ogg_encoder_aspect;
-       FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset;
-} OggFLAC__SeekableStreamEncoderProtected;
-
-#endif
index e737c36..a47a467 100644 (file)
@@ -38,6 +38,7 @@
 typedef struct OggFLAC__StreamEncoderProtected {
        OggFLAC__StreamEncoderState state;
        OggFLAC__OggEncoderAspect ogg_encoder_aspect;
+       FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset;
 } OggFLAC__StreamEncoderProtected;
 
 #endif
index 944d7c4..0f630d6 100644 (file)
@@ -92,14 +92,6 @@ LINK32=link.exe
 # PROP Default_Filter "c"\r
 # Begin Source File\r
 \r
-SOURCE=.\file_decoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\file_encoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\ogg_decoder_aspect.c\r
 # End Source File\r
 # Begin Source File\r
@@ -116,14 +108,6 @@ SOURCE=.\ogg_mapping.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\seekable_stream_decoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\seekable_stream_encoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\stream_decoder.c\r
 # End Source File\r
 # Begin Source File\r
@@ -164,22 +148,6 @@ SOURCE=.\include\protected\all.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\include\protected\file_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\file_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\seekable_stream_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\seekable_stream_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\include\protected\stream_decoder.h\r
 # End Source File\r
 # Begin Source File\r
@@ -200,22 +168,6 @@ SOURCE=..\..\include\OggFLAC\export.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\include\OggFLAC\file_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\OggFLAC\file_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\OggFLAC\seekable_stream_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\OggFLAC\seekable_stream_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\include\OggFLAC\stream_decoder.h\r
 # End Source File\r
 # Begin Source File\r
index 3cf1c22..466512a 100644 (file)
@@ -85,14 +85,6 @@ LIB32=link.exe -lib
 # PROP Default_Filter "c"\r
 # Begin Source File\r
 \r
-SOURCE=.\file_decoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\file_encoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\ogg_decoder_aspect.c\r
 # End Source File\r
 # Begin Source File\r
@@ -109,14 +101,6 @@ SOURCE=.\ogg_mapping.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\seekable_stream_decoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\seekable_stream_encoder.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\stream_decoder.c\r
 # End Source File\r
 # Begin Source File\r
@@ -157,22 +141,6 @@ SOURCE=.\include\protected\all.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\include\protected\file_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\file_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\seekable_stream_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\protected\seekable_stream_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\include\protected\stream_decoder.h\r
 # End Source File\r
 # Begin Source File\r
@@ -193,22 +161,6 @@ SOURCE=..\..\include\OggFLAC\export.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\include\OggFLAC\file_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\OggFLAC\file_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\OggFLAC\seekable_stream_decoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\include\OggFLAC\seekable_stream_encoder.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\include\OggFLAC\stream_decoder.h\r
 # End Source File\r
 # Begin Source File\r
index 06e2852..a85dd72 100644 (file)
@@ -102,7 +102,7 @@ void OggFLAC__ogg_decoder_aspect_reset(OggFLAC__OggDecoderAspect *aspect)
                aspect->need_serial_number = true;
 }
 
-OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, void *decoder, void *client_data)
+OggFLAC__OggDecoderAspectReadStatus OggFLAC__ogg_decoder_aspect_read_callback_wrapper(OggFLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], unsigned *bytes, OggFLAC__OggDecoderAspectReadCallbackProxy read_callback, const OggFLAC__StreamDecoder *decoder, void *client_data)
 {
        static const unsigned OGG_BYTES_CHUNK = 8192;
        const unsigned bytes_requested = *bytes;
index 0ca9eed..29796d3 100644 (file)
@@ -141,7 +141,7 @@ FLAC__StreamEncoderWriteStatus OggFLAC__ogg_encoder_aspect_write_callback_wrappe
                        if(bytes != FLAC__STREAM_METADATA_HEADER_LENGTH + FLAC__STREAM_METADATA_STREAMINFO_LENGTH) {
                                /*
                                 * If we get here, our assumption about the way write callbacks happen
-                                * explained above is wrong
+                                * (explained above) is wrong
                                 */
                                FLAC__ASSERT(0);
                                return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
index bebd7f0..ca98555 100644 (file)
 #include <string.h> /* for memcmp(), memcpy() */
 #include "FLAC/assert.h"
 #include "private/ogg_helper.h"
-#include "protected/seekable_stream_encoder.h"
+#include "protected/stream_encoder.h"
 
 
-static FLAC__bool full_read_(OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte *buffer, unsigned bytes, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data)
+static FLAC__bool full_read_(OggFLAC__StreamEncoder *encoder, FLAC__byte *buffer, unsigned bytes, OggFLAC__StreamEncoderReadCallback read_callback, void *client_data)
 {
        while(bytes > 0) {
                unsigned bytes_read = bytes;
                switch(read_callback(encoder, buffer, &bytes_read, client_data)) {
-                       case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE:
+                       case OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE:
                                bytes -= bytes_read;
                                buffer += bytes_read;
                                break;
-                       case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM:
+                       case OggFLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM:
                                if(bytes_read == 0) {
-                                       encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
+                                       encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
                                        return false;
                                }
                                bytes -= bytes_read;
                                buffer += bytes_read;
                                break;
-                       case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT:
-                               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR;
+                       case OggFLAC__STREAM_ENCODER_READ_STATUS_ABORT:
+                               encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
+                               return false;
+                       case OggFLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED:
                                return false;
                        default:
                                /* double protection: */
                                FLAC__ASSERT(0);
-                               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR;
+                               encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
                                return false;
                }
        }
@@ -88,11 +90,12 @@ void simple_ogg_page__clear(ogg_page *page)
        simple_ogg_page__init(page);
 }
 
-FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data)
+FLAC__bool simple_ogg_page__get_at(OggFLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, OggFLAC__StreamEncoderReadCallback read_callback, void *client_data)
 {
        static const unsigned OGG_HEADER_FIXED_PORTION_LEN = 27;
        static const unsigned OGG_MAX_HEADER_LEN = 27/*OGG_HEADER_FIXED_PORTION_LEN*/ + 255;
        FLAC__byte crc[4];
+       FLAC__StreamEncoderSeekStatus seek_status;
 
        FLAC__ASSERT(page->header == 0);
        FLAC__ASSERT(page->header_len == 0);
@@ -100,14 +103,17 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC
        FLAC__ASSERT(page->body_len == 0);
 
        /* move the stream pointer to the supposed beginning of the page */
-       if(seek_callback(encoder, position, client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
+       if(0 == seek_callback)
+               return false;
+       if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
+               if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
+                       encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
                return false;
        }
 
        /* allocate space for the page header */
        if(0 == (page->header = (unsigned char *)malloc(OGG_MAX_HEADER_LEN))) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
 
@@ -125,7 +131,7 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC
                memcmp(page->header+6, "\0\0\0\0\0\0\0\0", 8) || /* granulepos is non-zero */
                page->header[26] == 0                            /* packet is 0-size */
        ) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
                return false;
        }
 
@@ -139,7 +145,7 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC
                /* check to see that it specifies a single packet */
                for(i = 0; i < (unsigned)page->header[26] - 1; i++) {
                        if(page->header[i + OGG_HEADER_FIXED_PORTION_LEN] != 255) {
-                               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
+                               encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
                                return false;
                        }
                }
@@ -149,7 +155,7 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC
 
        /* allocate space for the page body */
        if(0 == (page->body = (unsigned char *)malloc(page->body_len))) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
 
@@ -161,31 +167,36 @@ FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC
        memcpy(crc, page->header+22, 4);
        ogg_page_checksum_set(page);
        if(memcmp(crc, page->header+22, 4)) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
                return false;
        }
 
        return true;
 }
 
-FLAC__bool simple_ogg_page__set_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderWriteCallback write_callback, void *client_data)
+FLAC__bool simple_ogg_page__set_at(OggFLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data)
 {
+       FLAC__StreamEncoderSeekStatus seek_status;
+
        FLAC__ASSERT(page->header != 0);
        FLAC__ASSERT(page->header_len != 0);
        FLAC__ASSERT(page->body != 0);
        FLAC__ASSERT(page->body_len != 0);
 
        /* move the stream pointer to the supposed beginning of the page */
-       if(seek_callback(encoder, position, client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
+       if(0 == seek_callback)
+               return false;
+       if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
+               if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
+                       encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
                return false;
        }
 
        ogg_page_checksum_set(page);
 
        /* re-write the page */
-       if(write_callback(encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
+       if(write_callback((FLAC__StreamEncoder*)encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
                return false;
        }
 
diff --git a/src/libOggFLAC/seekable_stream_decoder.c b/src/libOggFLAC/seekable_stream_decoder.c
deleted file mode 100644 (file)
index 9721ef8..0000000
+++ /dev/null
@@ -1,982 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h> /* for calloc() */
-#include <string.h> /* for memcpy()/memcmp() */
-#include "FLAC/assert.h"
-#include "protected/seekable_stream_decoder.h"
-#include "protected/stream_decoder.h"
-#include "../libFLAC/include/private/float.h" /* @@@ ugly hack, but how else to do?  we need to reuse the float formats but don't want to expose it */
-#include "../libFLAC/include/private/md5.h" /* @@@ ugly hack, but how else to do?  we need to reuse the md5 code but don't want to expose it */
-
-/***********************************************************************
- *
- * Private class method prototypes
- *
- ***********************************************************************/
-
-static void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder);
-static FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
-static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-static void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-static FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
-
-/***********************************************************************
- *
- * Private class data
- *
- ***********************************************************************/
-
-typedef struct OggFLAC__SeekableStreamDecoderPrivate {
-       OggFLAC__SeekableStreamDecoderReadCallback read_callback;
-       OggFLAC__SeekableStreamDecoderSeekCallback seek_callback;
-       OggFLAC__SeekableStreamDecoderTellCallback tell_callback;
-       OggFLAC__SeekableStreamDecoderLengthCallback length_callback;
-       OggFLAC__SeekableStreamDecoderEofCallback eof_callback;
-       OggFLAC__SeekableStreamDecoderWriteCallback write_callback;
-       OggFLAC__SeekableStreamDecoderMetadataCallback metadata_callback;
-       OggFLAC__SeekableStreamDecoderErrorCallback error_callback;
-       void *client_data;
-       OggFLAC__StreamDecoder *stream_decoder;
-       FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */
-       struct FLAC__MD5Context md5context;
-       FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */
-       FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
-       /* the rest of these are only used for seeking: */
-       FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */
-       const FLAC__StreamMetadata_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */
-       /* Since we always want to see the STREAMINFO and SEEK_TABLE blocks at this level, we need some extra flags to keep track of whether they should be passed on up through the metadata_callback */
-       FLAC__bool ignore_stream_info_block;
-       FLAC__bool ignore_seek_table_block;
-       FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
-       FLAC__uint64 target_sample;
-       FLAC__bool got_a_frame; /* hack needed in seek routine to check when process_single() actually writes a frame */
-} OggFLAC__SeekableStreamDecoderPrivate;
-
-/***********************************************************************
- *
- * Public static class data
- *
- ***********************************************************************/
-
-OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderStateString[] = {
-       "OggFLAC__SEEKABLE_STREAM_DECODER_OK",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED"
-};
-
-OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderReadStatusString[] = {
-       "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR"
-};
-
-OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderSeekStatusString[] = {
-       "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR"
-};
-
-OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderTellStatusString[] = {
-       "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR"
-};
-
-OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderLengthStatusString[] = {
-       "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK",
-       "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR"
-};
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- ***********************************************************************/
-
-OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new()
-{
-       OggFLAC__SeekableStreamDecoder *decoder;
-
-       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
-
-       decoder = (OggFLAC__SeekableStreamDecoder*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoder));
-       if(decoder == 0) {
-               return 0;
-       }
-
-       decoder->protected_ = (OggFLAC__SeekableStreamDecoderProtected*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderProtected));
-       if(decoder->protected_ == 0) {
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_ = (OggFLAC__SeekableStreamDecoderPrivate*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderPrivate));
-       if(decoder->private_ == 0) {
-               free(decoder->protected_);
-               free(decoder);
-               return 0;
-       }
-
-       decoder->private_->stream_decoder = OggFLAC__stream_decoder_new();
-       if(0 == decoder->private_->stream_decoder) {
-               free(decoder->private_);
-               free(decoder->protected_);
-               free(decoder);
-               return 0;
-       }
-
-       set_defaults_(decoder);
-
-       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
-
-       return decoder;
-}
-
-OggFLAC_API void OggFLAC__seekable_stream_decoder_delete(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-
-       (void)OggFLAC__seekable_stream_decoder_finish(decoder);
-
-       OggFLAC__stream_decoder_delete(decoder->private_->stream_decoder);
-
-       free(decoder->private_);
-       free(decoder->protected_);
-       free(decoder);
-}
-
-/***********************************************************************
- *
- * Public class methods
- *
- ***********************************************************************/
-
-OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_init(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED;
-
-       if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback)
-               return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
-
-       if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
-               return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
-
-       decoder->private_->seek_table = 0;
-
-       decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
-
-       /* We initialize the FLAC__MD5Context even though we may never use it.  This
-        * is because md5 checking may be turned on to start and then turned off if
-        * a seek occurs.  So we always init the context here and finalize it in
-        * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
-        * cleaned up properly.
-        */
-       FLAC__MD5Init(&decoder->private_->md5context);
-
-       OggFLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
-       OggFLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
-       OggFLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
-       OggFLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
-       OggFLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder);
-
-       /* We always want to see these blocks.  Whether or not we pass them up
-        * through the metadata callback will be determined by flags set in our
-        * implementation of ..._set_metadata_respond/ignore...()
-        */
-       OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO);
-       OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
-
-       if(OggFLAC__stream_decoder_init(decoder->private_->stream_decoder) != OggFLAC__STREAM_DECODER_OK)
-               return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool md5_failed = false;
-
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-
-       if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return true;
-
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-
-       /* see the comment in OggFLAC__seekable_stream_decoder_init() as to why we
-        * always call FLAC__MD5Final()
-        */
-       FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
-
-       OggFLAC__stream_decoder_finish(decoder->private_->stream_decoder);
-
-       if(decoder->private_->do_md5_checking) {
-               if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16))
-                       md5_failed = true;
-       }
-
-       set_defaults_(decoder);
-
-       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
-
-       return !md5_failed;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_md5_checking(OggFLAC__SeekableStreamDecoder *decoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->protected_->md5_checking = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_read_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderReadCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->read_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_seek_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderSeekCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->seek_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_tell_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderTellCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->tell_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_length_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderLengthCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->length_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_eof_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderEofCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->eof_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_write_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->write_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderMetadataCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->metadata_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_error_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderErrorCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->error_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_client_data(OggFLAC__SeekableStreamDecoder *decoder, void *value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->client_data = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_serial_number(OggFLAC__SeekableStreamDecoder *decoder, long value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       OggFLAC__stream_decoder_set_serial_number(decoder->private_->stream_decoder, value);
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       if(type == FLAC__METADATA_TYPE_STREAMINFO)
-               decoder->private_->ignore_stream_info_block = false;
-       else if(type == FLAC__METADATA_TYPE_SEEKTABLE)
-               decoder->private_->ignore_seek_table_block = false;
-       return OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->ignore_stream_info_block = false;
-       decoder->private_->ignore_seek_table_block = false;
-       return OggFLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       if(type == FLAC__METADATA_TYPE_STREAMINFO) {
-               decoder->private_->ignore_stream_info_block = true;
-               return true;
-       }
-       else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
-               decoder->private_->ignore_seek_table_block = true;
-               return true;
-       }
-       else
-               return OggFLAC__stream_decoder_set_metadata_ignore(decoder->private_->stream_decoder, type);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       return OggFLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->stream_decoder, id);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       FLAC__ASSERT(0 != decoder->private_->stream_decoder);
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->ignore_stream_info_block = true;
-       decoder->private_->ignore_seek_table_block = true;
-       return
-               OggFLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->stream_decoder) &&
-               OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO) &&
-               OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
-}
-
-OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       return decoder->protected_->state;
-}
-
-OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__stream_decoder_get_state(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API const char *OggFLAC__seekable_stream_decoder_get_resolved_state_string(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR)
-               return OggFLAC__SeekableStreamDecoderStateString[decoder->protected_->state];
-       else
-               return OggFLAC__stream_decoder_get_resolved_state_string(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_md5_checking(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->protected_);
-       return decoder->protected_->md5_checking;
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_channels(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__stream_decoder_get_channels(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API FLAC__ChannelAssignment OggFLAC__seekable_stream_decoder_get_channel_assignment(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__stream_decoder_get_channel_assignment(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_bits_per_sample(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__stream_decoder_get_bits_per_sample(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__stream_decoder_get_sample_rate(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       return OggFLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-
-       decoder->private_->do_md5_checking = false;
-
-       if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-
-       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
-
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_reset(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-
-       if(!OggFLAC__seekable_stream_decoder_flush(decoder)) {
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-
-       if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-
-       decoder->private_->seek_table = 0;
-
-       decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
-
-       /* We initialize the FLAC__MD5Context even though we may never use it.  This
-        * is because md5 checking may be turned on to start and then turned off if
-        * a seek occurs.  So we always init the context here and finalize it in
-        * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
-        * cleaned up properly.
-        */
-       FLAC__MD5Init(&decoder->private_->md5context);
-
-       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
-
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-
-       if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
-
-       ret = OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder);
-       if(!ret)
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-
-       if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
-
-       ret = OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder);
-       if(!ret)
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_stream(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__bool ret;
-       FLAC__ASSERT(0 != decoder);
-
-       if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-
-       if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
-               return true;
-
-       FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
-
-       ret = OggFLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder);
-       if(!ret)
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-
-       return ret;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_seek_absolute(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample)
-{
-       FLAC__uint64 length;
-
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM);
-
-       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING;
-
-       /* turn off md5 checking if a seek is attempted */
-       decoder->private_->do_md5_checking = false;
-
-       if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-       /* get the file length */
-       if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) {
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-               return false;
-       }
-       /* rewind */
-       if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-               return false;
-       }
-       if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) {
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-               return false;
-       }
-       if(decoder->private_->stream_info.total_samples > 0 && sample >= decoder->private_->stream_info.total_samples) {
-               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-               return false;
-       }
-
-       return seek_to_absolute_sample_(decoder, length, sample);
-}
-
-/***********************************************************************
- *
- * Private class methods
- *
- ***********************************************************************/
-
-void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder)
-{
-       decoder->private_->read_callback = 0;
-       decoder->private_->seek_callback = 0;
-       decoder->private_->tell_callback = 0;
-       decoder->private_->length_callback = 0;
-       decoder->private_->eof_callback = 0;
-       decoder->private_->write_callback = 0;
-       decoder->private_->metadata_callback = 0;
-       decoder->private_->error_callback = 0;
-       decoder->private_->client_data = 0;
-       /* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */
-       decoder->private_->ignore_stream_info_block = false;
-       decoder->private_->ignore_seek_table_block = true;
-
-       decoder->protected_->md5_checking = false;
-}
-
-FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-{
-       OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
-       (void)decoder;
-       if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
-               *bytes = 0;
-#if 0
-               /*@@@@@@ we used to do this: */
-               seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-               /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */
-#endif
-               return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-       }
-       else if(*bytes > 0) {
-               if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) {
-                       seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
-                       return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
-               }
-               if(*bytes == 0) {
-                       if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
-#if 0
-                               /*@@@@@@ we used to do this: */
-                               seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
-                               /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */
-#endif
-                               return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-                       }
-                       else
-                               return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-               }
-               else {
-                       return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-               }
-       }
-       else
-               return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
-}
-
-FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
-       (void)decoder;
-
-       if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
-               FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
-               FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
-               FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;
-
-               FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
-
-               seekable_stream_decoder->private_->got_a_frame = true;
-               seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */
-               if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
-                       unsigned delta = (unsigned)(target_sample - this_frame_sample);
-                       /* kick out of seek mode */
-                       seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
-                       /* shift out the samples before target_sample */
-                       if(delta > 0) {
-                               unsigned channel;
-                               const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
-                               for(channel = 0; channel < frame->header.channels; channel++)
-                                       newbuffer[channel] = buffer[channel] + delta;
-                               seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;
-                               seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
-                               /* write the relevant samples */
-                               return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);
-                       }
-                       else {
-                               /* write the relevant samples */
-                               return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
-                       }
-               }
-               else {
-                       return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
-               }
-       }
-       else {
-               if(seekable_stream_decoder->private_->do_md5_checking) {
-                       if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
-                               return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
-               }
-               return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
-       }
-}
-
-void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
-       (void)decoder;
-
-       if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
-               seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
-               /* save the MD5 signature for comparison later */
-               memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
-               if(0 == memcmp(seekable_stream_decoder->private_->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
-                       seekable_stream_decoder->private_->do_md5_checking = false;
-       }
-       else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
-               seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;
-       }
-
-       if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
-               FLAC__bool ignore_block = false;
-               if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)
-                       ignore_block = true;
-               else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)
-                       ignore_block = true;
-               if(!ignore_block)
-                       seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);
-       }
-}
-
-void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
-       (void)decoder;
-
-       if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)
-               seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
-}
-
-FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
-{
-       FLAC__uint64 left_pos = 0, right_pos = stream_length;
-       FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;
-       FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
-       FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
-       FLAC__bool did_a_seek;
-       unsigned iteration = 0;
-
-       /* In the first iterations, we will calculate the target byte position 
-        * by the distance from the target sample to left_sample and
-        * right_sample (let's call it "proportional search").  After that, we
-        * will switch to binary search.
-        */
-       unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
-
-       /* We will switch to a linear search once our current sample is less
-        * that this number of samples ahead of the target sample
-        */
-       static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
-
-       /* If the total number of samples is unknown, use a large value and
-        * increase 'iteration' to force binary search immediately.
-        */
-       if(right_sample == 0) {
-               right_sample = (FLAC__uint64)(-1);
-               BINARY_SEARCH_AFTER_ITERATION = 0;
-       }
-
-       decoder->private_->target_sample = target_sample;
-       for( ; ; iteration++) {
-               if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
-                       if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
-                               pos = (right_pos + left_pos) / 2;
-                       }
-                       else {
-#ifndef FLAC__INTEGER_ONLY_LIBRARY
-#if defined _MSC_VER || defined __MINGW32__
-                               /* with MSVC you have to spoon feed it the casting */
-                               pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos));
-#else
-                               pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos));
-#endif
-#else
-                               /* a little less accurate: */
-                               if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))
-                                       pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));
-                               else /* @@@ WATCHOUT, ~2TB limit */
-                                       pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));
-#endif
-                               /* @@@ TODO: might want to limit pos to some distance
-                                * before EOF, to make sure we land before the last frame,
-                                * thereby getting a this_fram_sample and so having a better
-                                * estimate.  this would also mostly (or totally if we could
-                                * be sure to land before the last frame) avoid the
-                                * end-of-stream case we have to check later.
-                                */
-                       }
-
-                       /* physical seek */
-                       if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
-                               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                               return false;
-                       }
-                       if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
-                               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-                               return false;
-                       }
-                       did_a_seek = true;
-               }
-               else
-                       did_a_seek = false;
-
-               decoder->private_->got_a_frame = false;
-               if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
-                       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                       return false;
-               }
-               if(!decoder->private_->got_a_frame) {
-                       if(did_a_seek) {
-                               /* this can happen if we seek to a point after the last frame; we drop
-                                * to binary search right away in this case to avoid any wasted
-                                * iterations of proportional search.
-                                */
-                               right_pos = pos;
-                               BINARY_SEARCH_AFTER_ITERATION = 0;
-                       }
-                       else {
-                               /* this can probably only happen if total_samples is unknown and the
-                                * target_sample is past the end of the stream
-                                */
-                               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                               return false;
-                       }
-               }
-               /* our write callback will change the state when it gets to the target frame */
-               else if(
-                       decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING &&
-                       decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
-               ) {
-                       break;
-               }
-               else {
-                       this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
-                       FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
-
-                       if (did_a_seek) {
-                               if (this_frame_sample <= target_sample) {
-                                       /* The 'equal' case should not happen, since
-                                        * OggFLAC__stream_decoder_process_single()
-                                        * should recognize that it has hit the
-                                        * target sample and we would exit through
-                                        * the 'break' above.
-                                        */
-                                       FLAC__ASSERT(this_frame_sample != target_sample);
-
-                                       left_sample = this_frame_sample;
-                                       /* sanity check to avoid infinite loop */
-                                       if (left_pos == pos) {
-                                               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                                               return false;
-                                       }
-                                       left_pos = pos;
-                               }
-                               else if(this_frame_sample > target_sample) {
-                                       right_sample = this_frame_sample;
-                                       /* sanity check to avoid infinite loop */
-                                       if (right_pos == pos) {
-                                               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                                               return false;
-                                       }
-                                       right_pos = pos;
-                               }
-                       }
-               }
-       }
-
-       return true;
-}
diff --git a/src/libOggFLAC/seekable_stream_encoder.c b/src/libOggFLAC/seekable_stream_encoder.c
deleted file mode 100644 (file)
index b222905..0000000
+++ /dev/null
@@ -1,1078 +0,0 @@
-/* libOggFLAC - Free Lossless Audio Codec + Ogg library
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * - Neither the name of the Xiph.org Foundation nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h> /* for calloc() */
-#include <string.h> /* for memcpy() */
-#include "FLAC/assert.h"
-#include "OggFLAC/seekable_stream_encoder.h"
-#include "protected/seekable_stream_encoder.h"
-#include "private/ogg_helper.h"
-
-#ifdef max
-#undef max
-#endif
-#define max(a,b) ((a)>(b)?(a):(b))
-
-/***********************************************************************
- *
- * Private class method prototypes
- *
- ***********************************************************************/
-
-/* unpublished debug routines */
-extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-
-static void set_defaults_(OggFLAC__SeekableStreamEncoder *encoder);
-static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
-static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
-
-
-/***********************************************************************
- *
- * Private class data
- *
- ***********************************************************************/
-
-typedef struct OggFLAC__SeekableStreamEncoderPrivate {
-       OggFLAC__SeekableStreamEncoderReadCallback read_callback;
-       OggFLAC__SeekableStreamEncoderSeekCallback seek_callback;
-       OggFLAC__SeekableStreamEncoderTellCallback tell_callback;
-       OggFLAC__SeekableStreamEncoderWriteCallback write_callback;
-       void *client_data;
-       FLAC__StreamEncoder *FLAC_stream_encoder;
-       FLAC__StreamMetadata_SeekTable *seek_table;
-       /* internal vars (all the above are class settings) */
-       unsigned first_seekpoint_to_check;
-       FLAC__uint64 samples_written;
-} OggFLAC__SeekableStreamEncoderPrivate;
-
-
-/***********************************************************************
- *
- * Public static class data
- *
- ***********************************************************************/
-
-OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderStateString[] = {
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_OK",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED"
-};
-
-OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderReadStatusString[] = {
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM",
-       "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT"
-};
-
-
-/***********************************************************************
- *
- * Class constructor/destructor
- *
- */
-OggFLAC_API OggFLAC__SeekableStreamEncoder *OggFLAC__seekable_stream_encoder_new()
-{
-       OggFLAC__SeekableStreamEncoder *encoder;
-
-       encoder = (OggFLAC__SeekableStreamEncoder*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoder));
-       if(encoder == 0) {
-               return 0;
-       }
-
-       encoder->protected_ = (OggFLAC__SeekableStreamEncoderProtected*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoderProtected));
-       if(encoder->protected_ == 0) {
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_ = (OggFLAC__SeekableStreamEncoderPrivate*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoderPrivate));
-       if(encoder->private_ == 0) {
-               free(encoder->protected_);
-               free(encoder);
-               return 0;
-       }
-
-       encoder->private_->FLAC_stream_encoder = FLAC__stream_encoder_new();
-       if(0 == encoder->private_->FLAC_stream_encoder) {
-               free(encoder->private_);
-               free(encoder->protected_);
-               free(encoder);
-               return 0;
-       }
-
-       set_defaults_(encoder);
-
-       encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED;
-
-       return encoder;
-}
-
-OggFLAC_API void OggFLAC__seekable_stream_encoder_delete(OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-
-       (void)OggFLAC__seekable_stream_encoder_finish(encoder);
-
-       FLAC__stream_encoder_delete(encoder->private_->FLAC_stream_encoder);
-
-       free(encoder->private_);
-       free(encoder->protected_);
-       free(encoder);
-}
-
-
-/***********************************************************************
- *
- * Public class methods
- *
- ***********************************************************************/
-
-OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_init(OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED;
-
-       if(0 == encoder->private_->seek_callback || 0 == encoder->private_->tell_callback || 0 == encoder->private_->write_callback)
-               return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK;
-
-       if(!OggFLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect))
-                       return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
-
-       if(0 != encoder->private_->seek_table && !FLAC__format_seektable_is_legal(encoder->private_->seek_table))
-               return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE;
-
-       /*
-        * These must be done before we init the stream encoder because that
-        * calls the write_callback, which uses these values.
-        */
-       encoder->private_->first_seekpoint_to_check = 0;
-       encoder->private_->samples_written = 0;
-       encoder->protected_->streaminfo_offset = 0;
-       encoder->protected_->seektable_offset = 0;
-       encoder->protected_->audio_offset = 0;
-
-       FLAC__stream_encoder_set_write_callback(encoder->private_->FLAC_stream_encoder, write_callback_);
-       FLAC__stream_encoder_set_metadata_callback(encoder->private_->FLAC_stream_encoder, metadata_callback_);
-       FLAC__stream_encoder_set_client_data(encoder->private_->FLAC_stream_encoder, encoder);
-
-       if(FLAC__stream_encoder_init(encoder->private_->FLAC_stream_encoder) != FLAC__STREAM_ENCODER_OK)
-               return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
-
-       /*
-        * Initializing the stream encoder writes all the metadata, so we
-        * save the stream offset now.
-        */
-       if(encoder->private_->tell_callback(encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK)
-               return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR;
-
-       return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OK;
-}
-
-OggFLAC_API void OggFLAC__seekable_stream_encoder_finish(OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-
-       if(encoder->protected_->state == OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return;
-
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-
-       FLAC__stream_encoder_finish(encoder->private_->FLAC_stream_encoder);
-
-       OggFLAC__ogg_encoder_aspect_finish(&encoder->protected_->ogg_encoder_aspect);
-
-       set_defaults_(encoder);
-
-       encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_serial_number(OggFLAC__SeekableStreamEncoder *encoder, long value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       OggFLAC__ogg_encoder_aspect_set_serial_number(&encoder->protected_->ogg_encoder_aspect, value);
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_verify(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_verify(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_streamable_subset(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_streamable_subset(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_channels(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_channels(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_bits_per_sample(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_sample_rate(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_sample_rate(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_blocksize(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_apodization(OggFLAC__SeekableStreamEncoder *encoder, const char *specification)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_apodization(encoder->private_->FLAC_stream_encoder, specification);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_lpc_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_escape_coding(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_total_samples_estimate(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       /* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */
-       if(0 != metadata && num_blocks > 1) {
-               unsigned i;
-               for(i = 1; i < num_blocks; i++) {
-                       if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
-                               FLAC__StreamMetadata *vc = metadata[i];
-                               for( ; i > 0; i--)
-                                       metadata[i] = metadata[i-1];
-                               metadata[0] = vc;
-                               break;
-                       }
-               }
-       }
-       if(0 != metadata && num_blocks > 0) {
-               unsigned i;
-               for(i = 0; i < num_blocks; i++) {
-                       /* keep track of any SEEKTABLE block */
-                       if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
-                               encoder->private_->seek_table = &metadata[i]->data.seek_table;
-                               break; /* take only the first one */
-                       }
-               }
-       }
-       if(!OggFLAC__ogg_encoder_aspect_set_num_metadata(&encoder->protected_->ogg_encoder_aspect, num_blocks))
-               return false;
-       return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_read_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderReadCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->read_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_seek_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderSeekCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->seek_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_tell_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderTellCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->tell_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_write_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->write_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_client_data(OggFLAC__SeekableStreamEncoder *encoder, void *value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->client_data = value;
-       return true;
-}
-
-/*
- * These three functions are not static, but not publically exposed in
- * include/FLAC/ either.  They are used by the test suite.
- */
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_constant_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_disable_constant_subframes(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_fixed_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_disable_fixed_subframes(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       return FLAC__stream_encoder_disable_verbatim_subframes(encoder->private_->FLAC_stream_encoder, value);
-}
-
-OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_get_state(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       return encoder->protected_->state;
-}
-
-OggFLAC_API FLAC__StreamEncoderState OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_state(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_encoder_get_verify_decoder_state(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API const char *OggFLAC__seekable_stream_encoder_get_resolved_state_string(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR)
-               return OggFLAC__SeekableStreamEncoderStateString[encoder->protected_->state];
-       else
-               return FLAC__stream_encoder_get_resolved_state_string(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API void OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       FLAC__stream_encoder_get_verify_decoder_error_stats(encoder->private_->FLAC_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_verify(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_verify(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_streamable_subset(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_streamable_subset(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_channels(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_channels(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_bits_per_sample(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_sample_rate(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_sample_rate(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_blocksize(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_max_lpc_order(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_escape_coding(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__uint64 OggFLAC__seekable_stream_encoder_get_total_samples_estimate(const OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       return FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_process(OggFLAC__SeekableStreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(!FLAC__stream_encoder_process(encoder->private_->FLAC_stream_encoder, buffer, samples)) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
-               return false;
-       }
-       else
-               return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_process_interleaved(OggFLAC__SeekableStreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
-       if(!FLAC__stream_encoder_process_interleaved(encoder->private_->FLAC_stream_encoder, buffer, samples)) {
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
-               return false;
-       }
-       else
-               return true;
-}
-
-/***********************************************************************
- *
- * Private class methods
- *
- ***********************************************************************/
-
-void set_defaults_(OggFLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-
-       encoder->private_->seek_callback = 0;
-       encoder->private_->tell_callback = 0;
-       encoder->private_->write_callback = 0;
-       encoder->private_->client_data = 0;
-
-       encoder->private_->seek_table = 0;
-
-       OggFLAC__ogg_encoder_aspect_set_defaults(&encoder->protected_->ogg_encoder_aspect);
-}
-
-FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data;
-       FLAC__StreamEncoderWriteStatus status;
-       FLAC__uint64 output_position;
-
-       (void)unused; /* silence compiler warning about unused parameter */
-       FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
-
-       if(encoder->private_->tell_callback(encoder, &output_position, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK)
-               return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR;
-
-       /*
-        * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets.
-        */
-       if(samples == 0) {
-               FLAC__MetadataType type = (buffer[0] & 0x7f);
-               if(type == FLAC__METADATA_TYPE_STREAMINFO)
-                       encoder->protected_->streaminfo_offset = output_position;
-               else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0)
-                       encoder->protected_->seektable_offset = output_position;
-       }
-
-       /*
-        * Mark the current seek point if hit (if audio_offset == 0 that
-        * means we're still writing metadata and haven't hit the first
-        * frame yet)
-        */
-       if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) {
-               const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder);
-               const FLAC__uint64 frame_first_sample = encoder->private_->samples_written;
-               const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
-               FLAC__uint64 test_sample;
-               unsigned i;
-               for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) {
-                       test_sample = encoder->private_->seek_table->points[i].sample_number;
-                       if(test_sample > frame_last_sample) {
-                               break;
-                       }
-                       else if(test_sample >= frame_first_sample) {
-                               encoder->private_->seek_table->points[i].sample_number = frame_first_sample;
-                               encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset;
-                               encoder->private_->seek_table->points[i].frame_samples = blocksize;
-                               encoder->private_->first_seekpoint_to_check++;
-                               /* DO NOT: "break;" and here's why:
-                                * The seektable template may contain more than one target
-                                * sample for any given frame; we will keep looping, generating
-                                * duplicate seekpoints for them, and we'll clean it up later,
-                                * just before writing the seektable back to the metadata.
-                                */
-                       }
-                       else {
-                               encoder->private_->first_seekpoint_to_check++;
-                       }
-               }
-       }
-
-       status = OggFLAC__ogg_encoder_aspect_write_callback_wrapper(&encoder->protected_->ogg_encoder_aspect, FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder), buffer, bytes, samples, current_frame, (OggFLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback, encoder, encoder->private_->client_data);
-
-       if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
-               encoder->private_->samples_written += samples;
-       }
-       else
-               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
-
-       return status;
-}
-
-void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data;
-       FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)];
-       const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
-       const unsigned min_framesize = metadata->data.stream_info.min_framesize;
-       const unsigned max_framesize = metadata->data.stream_info.max_framesize;
-       ogg_page page;
-
-       FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
-
-       /* We get called by the stream encoder when the encoding process
-        * has finished so that we can update the STREAMINFO and SEEKTABLE
-        * blocks.
-        */
-
-       (void)unused; /* silence compiler warning about unused parameter */
-       FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
-
-       /*@@@ reopen callback here?  The docs currently require user to open files in update mode from the start */
-
-       /* All this is based on intimate knowledge of the stream header
-        * layout, but a change to the header format that would break this
-        * would also break all streams encoded in the previous format.
-        */
-
-       /*
-        * Write STREAMINFO stats
-        */
-       simple_ogg_page__init(&page);
-       if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) {
-               simple_ogg_page__clear(&page);
-               return; /* state already set */
-       }
-       /*
-        * MD5 signature
-        */
-       {
-               const unsigned md5_offset =
-                       FLAC__STREAM_METADATA_HEADER_LENGTH +
-                       (
-                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
-                       ) / 8;
-
-               if(md5_offset + 16 > (unsigned)page.body_len) {
-                       encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
-                       simple_ogg_page__clear(&page);
-                       return;
-               }
-               memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16);
-       }
-       /*
-        * total samples
-        */
-       {
-               const unsigned total_samples_byte_offset =
-                       FLAC__STREAM_METADATA_HEADER_LENGTH +
-                       (
-                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
-                               - 4
-                       ) / 8;
-
-               if(total_samples_byte_offset + 5 > (unsigned)page.body_len) {
-                       encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
-                       simple_ogg_page__clear(&page);
-                       return;
-               }
-               b[0] = (FLAC__byte)page.body[total_samples_byte_offset] & 0xF0;
-               b[0] |= (FLAC__byte)((samples >> 32) & 0x0F);
-               b[1] = (FLAC__byte)((samples >> 24) & 0xFF);
-               b[2] = (FLAC__byte)((samples >> 16) & 0xFF);
-               b[3] = (FLAC__byte)((samples >> 8) & 0xFF);
-               b[4] = (FLAC__byte)(samples & 0xFF);
-               memcpy(page.body + total_samples_byte_offset, b, 5);
-       }
-       /*
-        * min/max framesize
-        */
-       {
-               const unsigned min_framesize_offset =
-                       FLAC__STREAM_METADATA_HEADER_LENGTH +
-                       (
-                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
-                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
-                       ) / 8;
-
-               if(min_framesize_offset + 6 > (unsigned)page.body_len) {
-                       encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
-                       simple_ogg_page__clear(&page);
-                       return;
-               }
-               b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF);
-               b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF);
-               b[2] = (FLAC__byte)(min_framesize & 0xFF);
-               b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF);
-               b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF);
-               b[5] = (FLAC__byte)(max_framesize & 0xFF);
-               memcpy(page.body + min_framesize_offset, b, 6);
-       }
-       if(!simple_ogg_page__set_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) {
-               simple_ogg_page__clear(&page);
-               return; /* state already set */
-       }
-       simple_ogg_page__clear(&page);
-
-       /*
-        * Write seektable
-        */
-       if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) {
-               unsigned i;
-               FLAC__byte *p;
-
-               FLAC__format_seektable_sort(encoder->private_->seek_table);
-
-               FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table));
-
-               simple_ogg_page__init(&page);
-               if(!simple_ogg_page__get_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) {
-                       simple_ogg_page__clear(&page);
-                       return; /* state already set */
-               }
-
-               if(FLAC__STREAM_METADATA_HEADER_LENGTH + (18*encoder->private_->seek_table->num_points) > (unsigned)page.body_len) {
-                       encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
-                       simple_ogg_page__clear(&page);
-                       return;
-               }
-
-               for(i = 0, p = page.body + FLAC__STREAM_METADATA_HEADER_LENGTH; i < encoder->private_->seek_table->num_points; i++, p += 18) {
-                       FLAC__uint64 xx;
-                       unsigned x;
-                       xx = encoder->private_->seek_table->points[i].sample_number;
-                       b[7] = (FLAC__byte)xx; xx >>= 8;
-                       b[6] = (FLAC__byte)xx; xx >>= 8;
-                       b[5] = (FLAC__byte)xx; xx >>= 8;
-                       b[4] = (FLAC__byte)xx; xx >>= 8;
-                       b[3] = (FLAC__byte)xx; xx >>= 8;
-                       b[2] = (FLAC__byte)xx; xx >>= 8;
-                       b[1] = (FLAC__byte)xx; xx >>= 8;
-                       b[0] = (FLAC__byte)xx; xx >>= 8;
-                       xx = encoder->private_->seek_table->points[i].stream_offset;
-                       b[15] = (FLAC__byte)xx; xx >>= 8;
-                       b[14] = (FLAC__byte)xx; xx >>= 8;
-                       b[13] = (FLAC__byte)xx; xx >>= 8;
-                       b[12] = (FLAC__byte)xx; xx >>= 8;
-                       b[11] = (FLAC__byte)xx; xx >>= 8;
-                       b[10] = (FLAC__byte)xx; xx >>= 8;
-                       b[9] = (FLAC__byte)xx; xx >>= 8;
-                       b[8] = (FLAC__byte)xx; xx >>= 8;
-                       x = encoder->private_->seek_table->points[i].frame_samples;
-                       b[17] = (FLAC__byte)x; x >>= 8;
-                       b[16] = (FLAC__byte)x; x >>= 8;
-                       if(encoder->private_->write_callback(encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
-                               encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
-                               simple_ogg_page__clear(&page);
-                               return;
-                       }
-                       memcpy(p, b, 18);
-               }
-
-               if(!simple_ogg_page__set_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) {
-                       simple_ogg_page__clear(&page);
-                       return; /* state already set */
-               }
-               simple_ogg_page__clear(&page);
-       }
-}
index 21557c6..aec6146 100644 (file)
 #  include <config.h>
 #endif
 
+#if defined _MSC_VER || defined __MINGW32__
+#include <io.h> /* for _setmode() */
+#include <fcntl.h> /* for _O_BINARY */
+#endif
+#if defined __CYGWIN__ || defined __EMX__
+#include <io.h> /* for setmode(), O_BINARY */
+#include <fcntl.h> /* for _O_BINARY */
+#endif
+#include <stdio.h>
 #include <stdlib.h> /* for calloc() */
+#include <sys/stat.h> /* for stat() */
+#include <sys/types.h> /* for off_t */
+#if defined _MSC_VER || defined __MINGW32__
+/*@@@ [2G limit] hacks for MSVC6 */
+#define fseeko fseek
+#define ftello ftell
+#endif
 #include "FLAC/assert.h"
 #include "protected/stream_decoder.h"
+#include "../libFLAC/include/private/float.h" /* @@@ ugly hack, but how else to do?  we need to reuse the float formats but don't want to expose it */
 
 /***********************************************************************
  *
  ***********************************************************************/
 
 static void set_defaults_(OggFLAC__StreamDecoder *decoder);
-static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FILE *get_binary_stdin_();
+static FLAC__StreamDecoderReadStatus read_callback2_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
 static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
 static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-static OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__bool seek_to_absolute_sample_(OggFLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
+static FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+static FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+static FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
+static FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data);
 
 
 /***********************************************************************
@@ -58,12 +83,21 @@ static OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void
  ***********************************************************************/
 
 typedef struct OggFLAC__StreamDecoderPrivate {
-       OggFLAC__StreamDecoderReadCallback read_callback;
-       OggFLAC__StreamDecoderWriteCallback write_callback;
-       OggFLAC__StreamDecoderMetadataCallback metadata_callback;
-       OggFLAC__StreamDecoderErrorCallback error_callback;
+       FLAC__StreamDecoderReadCallback read_callback;
+       FLAC__StreamDecoderSeekCallback seek_callback;
+       FLAC__StreamDecoderTellCallback tell_callback;
+       FLAC__StreamDecoderLengthCallback length_callback;
+       FLAC__StreamDecoderEofCallback eof_callback;
+       FLAC__StreamDecoderWriteCallback write_callback;
+       FLAC__StreamDecoderMetadataCallback metadata_callback;
+       FLAC__StreamDecoderErrorCallback error_callback;
        void *client_data;
-       FLAC__StreamDecoder *FLAC_stream_decoder;
+       FILE *file; /* only used if OggFLAC__stream_decoder_init_file()/OggFLAC__stream_decoder_init_file() called, else NULL */
+       /* the rest of these are only used for seeking: */
+       FLAC__bool is_seeking;
+       FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
+       FLAC__uint64 target_sample;
+       FLAC__bool got_a_frame; /* hack needed in seek routine to check when process_single() actually writes a frame */
 } OggFLAC__StreamDecoderPrivate;
 
 /***********************************************************************
@@ -76,12 +110,12 @@ OggFLAC_API const char * const OggFLAC__StreamDecoderStateString[] = {
        "OggFLAC__STREAM_DECODER_OK",
        "OggFLAC__STREAM_DECODER_END_OF_STREAM",
        "OggFLAC__STREAM_DECODER_OGG_ERROR",
-       "OggFLAC__STREAM_DECODER_READ_ERROR",
        "OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR",
+       "OggFLAC__STREAM_DECODER_SEEK_ERROR",
+       "OggFLAC__STREAM_DECODER_READ_ERROR",
        "OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
-       "OggFLAC__STREAM_DECODER_ALREADY_INITIALIZED",
-       "OggFLAC__STREAM_DECODER_INVALID_CALLBACK",
        "OggFLAC__STREAM_DECODER_UNINITIALIZED"
+       //@@@@@@
 };
 
 
@@ -93,6 +127,9 @@ OggFLAC_API const char * const OggFLAC__StreamDecoderStateString[] = {
 OggFLAC_API OggFLAC__StreamDecoder *OggFLAC__stream_decoder_new()
 {
        OggFLAC__StreamDecoder *decoder;
+       FLAC__StreamDecoder *parent;
+
+       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
 
        decoder = (OggFLAC__StreamDecoder*)calloc(1, sizeof(OggFLAC__StreamDecoder));
        if(decoder == 0) {
@@ -112,13 +149,16 @@ OggFLAC_API OggFLAC__StreamDecoder *OggFLAC__stream_decoder_new()
                return 0;
        }
 
-       decoder->private_->FLAC_stream_decoder = FLAC__stream_decoder_new();
-       if(0 == decoder->private_->FLAC_stream_decoder) {
+       parent = FLAC__stream_decoder_new();
+       if(0 == parent) {
                free(decoder->private_);
                free(decoder->protected_);
                free(decoder);
                return 0;
        }
+       decoder->super_ = *parent;
+
+       decoder->private_->file = 0;
 
        set_defaults_(decoder);
 
@@ -132,15 +172,15 @@ OggFLAC_API void OggFLAC__stream_decoder_delete(OggFLAC__StreamDecoder *decoder)
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->protected_);
        FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->private_->FLAC_stream_decoder);
 
        OggFLAC__stream_decoder_finish(decoder);
 
-       FLAC__stream_decoder_delete(decoder->private_->FLAC_stream_decoder);
-
        free(decoder->private_);
        free(decoder->protected_);
-       free(decoder);
+       /* don't free(decoder) because FLAC__stream_decoder_delete() will do it */
+
+       /* call superclass destructor last */
+       FLAC__stream_decoder_delete((FLAC__StreamDecoder*)decoder);
 }
 
 /***********************************************************************
@@ -149,104 +189,192 @@ OggFLAC_API void OggFLAC__stream_decoder_delete(OggFLAC__StreamDecoder *decoder)
  *
  ***********************************************************************/
 
-OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__stream_decoder_init(OggFLAC__StreamDecoder *decoder)
+OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_stream(
+       OggFLAC__StreamDecoder *decoder,
+       FLAC__StreamDecoderReadCallback read_callback,
+       FLAC__StreamDecoderSeekCallback seek_callback,
+       FLAC__StreamDecoderTellCallback tell_callback,
+       FLAC__StreamDecoderLengthCallback length_callback,
+       FLAC__StreamDecoderEofCallback eof_callback,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+)
 {
        FLAC__ASSERT(0 != decoder);
 
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
-               return decoder->protected_->state = OggFLAC__STREAM_DECODER_ALREADY_INITIALIZED;
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED;
 
-       if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
-               return decoder->protected_->state = OggFLAC__STREAM_DECODER_INVALID_CALLBACK;
+       if(
+               0 == read_callback ||
+               0 == write_callback ||
+               0 == error_callback ||
+               (seek_callback && (0 == tell_callback || 0 == length_callback || 0 == eof_callback))
+       )
+               return FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS;
 
        if(!OggFLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect))
                return decoder->protected_->state = OggFLAC__STREAM_DECODER_OGG_ERROR;
 
-       FLAC__stream_decoder_set_read_callback(decoder->private_->FLAC_stream_decoder, read_callback_);
-       FLAC__stream_decoder_set_write_callback(decoder->private_->FLAC_stream_decoder, write_callback_);
-       FLAC__stream_decoder_set_metadata_callback(decoder->private_->FLAC_stream_decoder, metadata_callback_);
-       FLAC__stream_decoder_set_error_callback(decoder->private_->FLAC_stream_decoder, error_callback_);
-       FLAC__stream_decoder_set_client_data(decoder->private_->FLAC_stream_decoder, decoder);
+       /* from here on, errors are fatal */
+
+       decoder->private_->read_callback = read_callback;
+       decoder->private_->seek_callback = seek_callback;
+       decoder->private_->tell_callback = tell_callback;
+       decoder->private_->length_callback = length_callback;
+       decoder->private_->eof_callback = eof_callback;
+       decoder->private_->write_callback = write_callback;
+       decoder->private_->metadata_callback = metadata_callback;
+       decoder->private_->error_callback = error_callback;
+       decoder->private_->client_data = client_data;
+
+       decoder->private_->is_seeking = false;
 
-       if(FLAC__stream_decoder_init(decoder->private_->FLAC_stream_decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
+       if(FLAC__stream_decoder_init_stream((FLAC__StreamDecoder*)decoder, read_callback_ogg_aspect_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, write_callback_, metadata_callback_, error_callback_, /*client_data=*/decoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK) \
                return decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
 
-       return decoder->protected_->state = OggFLAC__STREAM_DECODER_OK;
+       decoder->protected_->state = OggFLAC__STREAM_DECODER_OK;
+       return FLAC__STREAM_DECODER_INIT_STATUS_OK;
 }
 
-OggFLAC_API void OggFLAC__stream_decoder_finish(OggFLAC__StreamDecoder *decoder)
+OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_FILE(
+       OggFLAC__StreamDecoder *decoder,
+       FILE *file,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+)
 {
        FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
+       FLAC__ASSERT(0 != file);
 
-       if(decoder->protected_->state == OggFLAC__STREAM_DECODER_UNINITIALIZED)
-               return;
+       if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED;
 
-       FLAC__ASSERT(0 != decoder->private_->FLAC_stream_decoder);
+       if(0 == write_callback || 0 == error_callback)
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS;
 
-       FLAC__stream_decoder_finish(decoder->private_->FLAC_stream_decoder);
+       /*
+        * To make sure that our file does not go unclosed after an error, we
+        * must assign the FILE pointer before any further error can occur in
+        * this routine.
+        */
+       if(file == stdin)
+               file = get_binary_stdin_(); /* just to be safe */
 
-       OggFLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect);
+       decoder->private_->file = file;
 
-       set_defaults_(decoder);
+#ifdef OLD_STAT_WAY //@@@@@@
+       if(0 != decoder->private_->filename) {
+               free(decoder->private_->filename);
+               decoder->private_->filename = 0;
+       }
+       if(filename) {
+               if(0 == (decoder->private_->filename = strdup(filename))) {
+                       decoder->protected_->state = OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+                       return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR;
+               }
+       }
+#endif
 
-       decoder->protected_->state = OggFLAC__STREAM_DECODER_UNINITIALIZED;
+       return OggFLAC__stream_decoder_init_stream(
+               decoder,
+               file_read_callback_,
+               decoder->private_->file == stdin? 0: file_seek_callback_,
+               decoder->private_->file == stdin? 0: file_tell_callback_,/*@@@@@@ might work for stdin*/
+               decoder->private_->file == stdin? 0: file_length_callback_,
+               decoder->private_->file == stdin? 0: file_eof_callback_,/*@@@@@@ might work for stdin*/
+               write_callback,
+               metadata_callback,
+               error_callback,
+               client_data
+       );
 }
 
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_read_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderReadCallback value)
+OggFLAC_API FLAC__StreamDecoderInitStatus OggFLAC__stream_decoder_init_file(
+       OggFLAC__StreamDecoder *decoder,
+       const char *filename,
+       FLAC__StreamDecoderWriteCallback write_callback,
+       FLAC__StreamDecoderMetadataCallback metadata_callback,
+       FLAC__StreamDecoderErrorCallback error_callback,
+       void *client_data
+)
 {
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->read_callback = value;
-       return true;
-}
+       FILE *file;
 
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_write_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderWriteCallback value)
-{
        FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->write_callback = value;
-       return true;
-}
 
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderMetadataCallback value)
-{
-       FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
-       FLAC__ASSERT(0 != decoder->protected_);
+       /*
+        * To make sure that our file does not go unclosed after an error, we
+        * have to do the same entrance checks here that are later performed
+        * in OggFLAC__stream_decoder_init_FILE() before the FILE* is assigned.
+        */
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->metadata_callback = value;
-       return true;
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED;
+
+       if(0 == write_callback || 0 == error_callback)
+               return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS;
+
+       file = filename? fopen(filename, "rb") : stdin;
+
+       if(0 == file)
+               return FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE;
+
+#ifdef OLD_STAT_WAY //@@@@@@
+       if(0 != decoder->private_->filename) {
+               free(decoder->private_->filename);
+               decoder->private_->filename = 0;
+       }
+       if(filename) {
+               if(0 == (decoder->private_->filename = strdup(filename))) {
+                       decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+                       return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR;
+               }
+       }
+#endif
+
+       return OggFLAC__stream_decoder_init_FILE(decoder, file, write_callback, metadata_callback, error_callback, client_data);
 }
 
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_error_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderErrorCallback value)
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_finish(OggFLAC__StreamDecoder *decoder)
 {
+       FLAC__bool md5_ok;
+
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
        FLAC__ASSERT(0 != decoder->protected_);
-       if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
-               return false;
-       decoder->private_->error_callback = value;
-       return true;
+
+       if(decoder->protected_->state == OggFLAC__STREAM_DECODER_UNINITIALIZED)
+               return true;
+
+       md5_ok = FLAC__stream_decoder_finish((FLAC__StreamDecoder*)decoder);
+
+       OggFLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect);
+
+       if(0 != decoder->private_->file && decoder->private_->file != stdin) {
+               fclose(decoder->private_->file);
+               decoder->private_->file = 0;
+       }
+
+       decoder->private_->is_seeking = false;
+
+       set_defaults_(decoder);
+
+       decoder->protected_->state = OggFLAC__STREAM_DECODER_UNINITIALIZED;
+
+       return md5_ok;
 }
 
-OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_client_data(OggFLAC__StreamDecoder *decoder, void *value)
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_md5_checking(OggFLAC__StreamDecoder *decoder, FLAC__bool value)
 {
        FLAC__ASSERT(0 != decoder);
-       FLAC__ASSERT(0 != decoder->private_);
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
                return false;
-       decoder->private_->client_data = value;
-       return true;
+       return FLAC__stream_decoder_set_md5_checking((FLAC__StreamDecoder*)decoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_serial_number(OggFLAC__StreamDecoder *decoder, long value)
@@ -267,7 +395,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond(OggFLAC__Str
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_decoder_set_metadata_respond(decoder->private_->FLAC_stream_decoder, type);
+       return FLAC__stream_decoder_set_metadata_respond((FLAC__StreamDecoder*)decoder, type);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_application(OggFLAC__StreamDecoder *decoder, const FLAC__byte id[4])
@@ -277,7 +405,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_application(
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_decoder_set_metadata_respond_application(decoder->private_->FLAC_stream_decoder, id);
+       return FLAC__stream_decoder_set_metadata_respond_application((FLAC__StreamDecoder*)decoder, id);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_all(OggFLAC__StreamDecoder *decoder)
@@ -287,7 +415,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_all(OggFLAC_
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_decoder_set_metadata_respond_all(decoder->private_->FLAC_stream_decoder);
+       return FLAC__stream_decoder_set_metadata_respond_all((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore(OggFLAC__StreamDecoder *decoder, FLAC__MetadataType type)
@@ -297,7 +425,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore(OggFLAC__Stre
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_decoder_set_metadata_ignore(decoder->private_->FLAC_stream_decoder, type);
+       return FLAC__stream_decoder_set_metadata_ignore((FLAC__StreamDecoder*)decoder, type);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_application(OggFLAC__StreamDecoder *decoder, const FLAC__byte id[4])
@@ -307,7 +435,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_application(O
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->FLAC_stream_decoder, id);
+       return FLAC__stream_decoder_set_metadata_ignore_application((FLAC__StreamDecoder*)decoder, id);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_all(OggFLAC__StreamDecoder *decoder)
@@ -317,7 +445,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_all(OggFLAC__
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->FLAC_stream_decoder);
+       return FLAC__stream_decoder_set_metadata_ignore_all((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__stream_decoder_get_state(const OggFLAC__StreamDecoder *decoder)
@@ -331,7 +459,7 @@ OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_decoder_get_FLAC_stream_dec
 {
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder);
+       return FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API const char *OggFLAC__stream_decoder_get_resolved_state_string(const OggFLAC__StreamDecoder *decoder)
@@ -339,42 +467,56 @@ OggFLAC_API const char *OggFLAC__stream_decoder_get_resolved_state_string(const
        if(decoder->protected_->state != OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR)
                return OggFLAC__StreamDecoderStateString[decoder->protected_->state];
        else
-               return FLAC__stream_decoder_get_resolved_state_string(decoder->private_->FLAC_stream_decoder);
+               return FLAC__stream_decoder_get_resolved_state_string((FLAC__StreamDecoder*)decoder);
+}
+
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_get_md5_checking(const OggFLAC__StreamDecoder *decoder)
+{
+       FLAC__ASSERT(0 != decoder);
+       FLAC__ASSERT(0 != decoder->private_);
+       return FLAC__stream_decoder_get_md5_checking((FLAC__StreamDecoder*)decoder);
+}
+
+OggFLAC_API FLAC__uint64 OggFLAC__stream_decoder_get_total_samples(const OggFLAC__StreamDecoder *decoder)
+{
+       FLAC__ASSERT(0 != decoder);
+       FLAC__ASSERT(0 != decoder->private_);
+       return FLAC__stream_decoder_get_total_samples((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_decoder_get_channels(const OggFLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_channels(decoder->private_->FLAC_stream_decoder);
+       return FLAC__stream_decoder_get_channels((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API FLAC__ChannelAssignment OggFLAC__stream_decoder_get_channel_assignment(const OggFLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_channel_assignment(decoder->private_->FLAC_stream_decoder);
+       return FLAC__stream_decoder_get_channel_assignment((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_decoder_get_bits_per_sample(const OggFLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_bits_per_sample(decoder->private_->FLAC_stream_decoder);
+       return FLAC__stream_decoder_get_bits_per_sample((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_decoder_get_sample_rate(const OggFLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_sample_rate(decoder->private_->FLAC_stream_decoder);
+       return FLAC__stream_decoder_get_sample_rate((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_decoder_get_blocksize(const OggFLAC__StreamDecoder *decoder)
 {
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
-       return FLAC__stream_decoder_get_blocksize(decoder->private_->FLAC_stream_decoder);
+       return FLAC__stream_decoder_get_blocksize((FLAC__StreamDecoder*)decoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_flush(OggFLAC__StreamDecoder *decoder)
@@ -385,7 +527,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_flush(OggFLAC__StreamDecoder *dec
 
        OggFLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect);
 
-       if(!FLAC__stream_decoder_flush(decoder->private_->FLAC_stream_decoder)) {
+       if(!FLAC__stream_decoder_flush((FLAC__StreamDecoder*)decoder)) {
                decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
                return false;
        }
@@ -408,7 +550,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_reset(OggFLAC__StreamDecoder *dec
 
        OggFLAC__ogg_decoder_aspect_reset(&decoder->protected_->ogg_decoder_aspect);
 
-       if(!FLAC__stream_decoder_reset(decoder->private_->FLAC_stream_decoder)) {
+       if(!FLAC__stream_decoder_reset((FLAC__StreamDecoder*)decoder)) {
                decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
                return false;
        }
@@ -423,7 +565,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_single(OggFLAC__StreamDec
        FLAC__bool ret;
        FLAC__ASSERT(0 != decoder);
 
-       if(FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
+       if(FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
                decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM;
 
        if(decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
@@ -431,7 +573,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_single(OggFLAC__StreamDec
 
        FLAC__ASSERT(decoder->protected_->state == OggFLAC__STREAM_DECODER_OK);
 
-       ret = FLAC__stream_decoder_process_single(decoder->private_->FLAC_stream_decoder);
+       ret = FLAC__stream_decoder_process_single((FLAC__StreamDecoder*)decoder);
        if(!ret)
                decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
 
@@ -443,7 +585,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_metadata(Ogg
        FLAC__bool ret;
        FLAC__ASSERT(0 != decoder);
 
-       if(FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
+       if(FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
                decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM;
 
        if(decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
@@ -451,7 +593,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_metadata(Ogg
 
        FLAC__ASSERT(decoder->protected_->state == OggFLAC__STREAM_DECODER_OK);
 
-       ret = FLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->FLAC_stream_decoder);
+       ret = FLAC__stream_decoder_process_until_end_of_metadata((FLAC__StreamDecoder*)decoder);
        if(!ret)
                decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
 
@@ -463,7 +605,27 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_stream(OggFL
        FLAC__bool ret;
        FLAC__ASSERT(0 != decoder);
 
-       if(FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
+       if(FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
+               decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM;
+
+       if(decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
+               return true;
+
+       FLAC__ASSERT(decoder->protected_->state == OggFLAC__STREAM_DECODER_OK);
+
+       ret = FLAC__stream_decoder_process_until_end_of_stream((FLAC__StreamDecoder*)decoder);
+       if(!ret)
+               decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
+
+       return ret;
+}
+
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_skip_single_frame(OggFLAC__StreamDecoder *decoder)
+{
+       FLAC__bool ret;
+       FLAC__ASSERT(0 != decoder);
+
+       if(FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
                decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM;
 
        if(decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
@@ -471,13 +633,66 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_stream(OggFL
 
        FLAC__ASSERT(decoder->protected_->state == OggFLAC__STREAM_DECODER_OK);
 
-       ret = FLAC__stream_decoder_process_until_end_of_stream(decoder->private_->FLAC_stream_decoder);
+       ret = FLAC__stream_decoder_skip_single_frame((FLAC__StreamDecoder*)decoder);
        if(!ret)
                decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
 
        return ret;
 }
 
+OggFLAC_API FLAC__bool OggFLAC__stream_decoder_seek_absolute(OggFLAC__StreamDecoder *decoder, FLAC__uint64 sample)
+{
+       FLAC__uint64 length;
+
+       FLAC__ASSERT(0 != decoder);
+
+       if(decoder->protected_->state != OggFLAC__STREAM_DECODER_OK && decoder->protected_->state != OggFLAC__STREAM_DECODER_END_OF_STREAM)
+               return false;
+
+       if(0 == decoder->private_->seek_callback)
+               return false;
+
+       FLAC__ASSERT(decoder->private_->seek_callback);
+       FLAC__ASSERT(decoder->private_->tell_callback);
+       FLAC__ASSERT(decoder->private_->length_callback);
+       FLAC__ASSERT(decoder->private_->eof_callback);
+
+       if(OggFLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= OggFLAC__stream_decoder_get_total_samples(decoder))
+               return false;
+
+       decoder->private_->is_seeking = true;
+
+       /* get the file length (currently our algorithm needs to know the length so it's also an error to get FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED) */
+       if(decoder->private_->length_callback((FLAC__StreamDecoder*)decoder, &length, decoder->private_->client_data) != FLAC__STREAM_DECODER_LENGTH_STATUS_OK) {
+               decoder->private_->is_seeking = false;
+               return false;
+       }
+
+       /* if we haven't finished processing the metadata yet, do that so we have the STREAMINFO */
+       if(
+               FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA ||
+               FLAC__stream_decoder_get_state((FLAC__StreamDecoder*)decoder) == FLAC__STREAM_DECODER_READ_METADATA
+       ) {
+               if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder)) {
+                       /* above call sets the state for us */
+                       decoder->private_->is_seeking = false;
+                       return false;
+               }
+               /* check this again in case we didn't know total_samples the first time */
+               if(OggFLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= OggFLAC__stream_decoder_get_total_samples(decoder)) {
+                       decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR;
+                       decoder->private_->is_seeking = false;
+                       return false;
+               }
+       }
+
+       {
+               FLAC__bool ok = seek_to_absolute_sample_(decoder, length, sample);
+               decoder->private_->is_seeking = false;
+               return ok;
+       }
+}
+
 
 /***********************************************************************
  *
@@ -488,6 +703,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_stream(OggFL
 void set_defaults_(OggFLAC__StreamDecoder *decoder)
 {
        decoder->private_->read_callback = 0;
+       decoder->private_->seek_callback = 0;
+       decoder->private_->tell_callback = 0;
+       decoder->private_->length_callback = 0;
+       decoder->private_->eof_callback = 0;
        decoder->private_->write_callback = 0;
        decoder->private_->metadata_callback = 0;
        decoder->private_->error_callback = 0;
@@ -495,11 +714,67 @@ void set_defaults_(OggFLAC__StreamDecoder *decoder)
        OggFLAC__ogg_decoder_aspect_set_defaults(&decoder->protected_->ogg_decoder_aspect);
 }
 
-FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *unused, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+/*
+ * This will forcibly set stdin to binary mode (for OSes that require it)
+ */
+FILE *get_binary_stdin_()
 {
-       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data;
+       /* if something breaks here it is probably due to the presence or
+        * absence of an underscore before the identifiers 'setmode',
+        * 'fileno', and/or 'O_BINARY'; check your system header files.
+        */
+#if defined _MSC_VER || defined __MINGW32__
+       _setmode(_fileno(stdin), _O_BINARY);
+#elif defined __CYGWIN__ || defined __EMX__
+       /* almost certainly not needed for any modern Cygwin, but let's be safe... */
+       setmode(_fileno(stdin), _O_BINARY);
+#endif
 
-       (void)unused;
+       return stdin;
+}
+
+FLAC__StreamDecoderReadStatus read_callback2_(const FLAC__StreamDecoder *super, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+       const OggFLAC__StreamDecoder *decoder = (const OggFLAC__StreamDecoder *)super;
+       (void)client_data;
+       if(decoder->private_->eof_callback && decoder->private_->eof_callback((FLAC__StreamDecoder*)decoder, decoder->private_->client_data)) {
+               *bytes = 0;
+#if 0
+               /*@@@@@@ we used to do this: */
+               stream_decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM;
+               /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */
+#endif
+               return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+       }
+       else if(*bytes > 0) {
+               const FLAC__StreamDecoderReadStatus status = decoder->private_->read_callback(super, buffer, bytes, decoder->private_->client_data);
+               if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) {
+                       decoder->protected_->state = OggFLAC__STREAM_DECODER_READ_ERROR;
+                       return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+               }
+               else if(*bytes == 0) {
+                       if(status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM || (decoder->private_->eof_callback && decoder->private_->eof_callback((FLAC__StreamDecoder*)decoder, decoder->private_->client_data))) {
+#if 0
+                               /*@@@@@@ we used to do this: */
+                               stream_decoder->protected_->state = OggFLAC__STREAM_DECODER_END_OF_STREAM;
+                               /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */
+#endif
+                               return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+                       }
+                       else
+                               return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+               }
+               else
+                       return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+       }
+       else
+               return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
+}
+
+FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *super, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+       const OggFLAC__StreamDecoder *decoder = (const OggFLAC__StreamDecoder *)super;
+       (void)client_data;
 
        switch(OggFLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder, decoder->private_->client_data)) {
                case OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK:
@@ -528,32 +803,11 @@ FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *unused,
        }
 }
 
-FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *unused, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data;
-       (void)unused;
-       return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data);
-}
-
-void metadata_callback_(const FLAC__StreamDecoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data;
-       (void)unused;
-       decoder->private_->metadata_callback(decoder, metadata, decoder->private_->client_data);
-}
-
-void error_callback_(const FLAC__StreamDecoder *unused, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data;
-       (void)unused;
-       decoder->private_->error_callback(decoder, status, decoder->private_->client_data);
-}
-
 OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
 {
        OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)void_decoder;
 
-       switch(decoder->private_->read_callback(decoder, buffer, bytes, client_data)) {
+       switch(read_callback2_((FLAC__StreamDecoder*)decoder, buffer, bytes, client_data)) {
                case FLAC__STREAM_DECODER_READ_STATUS_CONTINUE:
                        return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_OK;
                case FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM:
@@ -566,3 +820,276 @@ OggFLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decode
                        return OggFLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
        }
 }
+
+FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *super, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+{
+       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super;
+       (void)client_data;
+
+       if(decoder->private_->is_seeking) {
+               FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
+               FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
+               FLAC__uint64 target_sample = decoder->private_->target_sample;
+
+               FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
+
+               decoder->private_->got_a_frame = true;
+               decoder->private_->last_frame = *frame; /* save the frame */
+               if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
+                       unsigned delta = (unsigned)(target_sample - this_frame_sample);
+                       /* kick out of seek mode */
+                       decoder->private_->is_seeking = false;
+                       /* shift out the samples before target_sample */
+                       if(delta > 0) {
+                               unsigned channel;
+                               const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
+                               for(channel = 0; channel < frame->header.channels; channel++)
+                                       newbuffer[channel] = buffer[channel] + delta;
+                               decoder->private_->last_frame.header.blocksize -= delta;
+                               decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
+                               /* write the relevant samples */
+                               return decoder->private_->write_callback((FLAC__StreamDecoder*)decoder, &decoder->private_->last_frame, newbuffer, decoder->private_->client_data);
+                       }
+                       else {
+                               /* write the relevant samples */
+                               return decoder->private_->write_callback((FLAC__StreamDecoder*)decoder, frame, buffer, decoder->private_->client_data);
+                       }
+               }
+               else {
+                       return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+               }
+       }
+       else
+               return decoder->private_->write_callback((FLAC__StreamDecoder*)decoder, frame, buffer, decoder->private_->client_data);
+}
+
+void metadata_callback_(const FLAC__StreamDecoder *super, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super;
+       (void)client_data;
+
+       if(!decoder->private_->is_seeking)
+               decoder->private_->metadata_callback((FLAC__StreamDecoder*)decoder, metadata, decoder->private_->client_data);
+}
+
+void error_callback_(const FLAC__StreamDecoder *super, FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super;
+       (void)client_data;
+
+       if(!decoder->private_->is_seeking)
+               decoder->private_->error_callback((FLAC__StreamDecoder*)decoder, status, decoder->private_->client_data);
+}
+
+FLAC__bool seek_to_absolute_sample_(OggFLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
+{
+       FLAC__uint64 left_pos = 0, right_pos = stream_length;
+       FLAC__uint64 left_sample = 0, right_sample = OggFLAC__stream_decoder_get_total_samples(decoder);
+       FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
+       FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
+       FLAC__bool did_a_seek;
+       unsigned iteration = 0;
+
+       /* In the first iterations, we will calculate the target byte position 
+        * by the distance from the target sample to left_sample and
+        * right_sample (let's call it "proportional search").  After that, we
+        * will switch to binary search.
+        */
+       unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
+
+       /* We will switch to a linear search once our current sample is less
+        * than this number of samples ahead of the target sample
+        */
+       static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
+
+       /* If the total number of samples is unknown, use a large value, and
+        * force binary search immediately.
+        */
+       if(right_sample == 0) {
+               right_sample = (FLAC__uint64)(-1);
+               BINARY_SEARCH_AFTER_ITERATION = 0;
+       }
+
+       decoder->private_->target_sample = target_sample;
+       for( ; ; iteration++) {
+               if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
+                       if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
+                               pos = (right_pos + left_pos) / 2;
+                       }
+                       else {
+#ifndef FLAC__INTEGER_ONLY_LIBRARY
+#if defined _MSC_VER || defined __MINGW32__
+                               /* with MSVC you have to spoon feed it the casting */
+                               pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos));
+#else
+                               pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos));
+#endif
+#else
+                               /* a little less accurate: */
+                               if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))
+                                       pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));
+                               else /* @@@ WATCHOUT, ~2TB limit */
+                                       pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));
+#endif
+                               /* @@@ TODO: might want to limit pos to some distance
+                                * before EOF, to make sure we land before the last frame,
+                                * thereby getting a this_fram_sample and so having a better
+                                * estimate.  @@@@@@DELETE:this would also mostly (or totally if we could
+                                * be sure to land before the last frame) avoid the
+                                * end-of-stream case we have to check later.
+                                */
+                       }
+
+                       /* physical seek */
+                       if(decoder->private_->seek_callback((FLAC__StreamDecoder*)decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) {
+                               decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR;
+                               return false;
+                       }
+                       if(!OggFLAC__stream_decoder_flush(decoder)) {
+                               /* above call sets the state for us */
+                               return false;
+                       }
+                       did_a_seek = true;
+               }
+               else
+                       did_a_seek = false;
+
+               decoder->private_->got_a_frame = false;
+               if(!OggFLAC__stream_decoder_process_single(decoder)) {
+                       decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR;
+                       return false;
+               }
+               if(!decoder->private_->got_a_frame) {
+                       if(did_a_seek) {
+                               /* this can happen if we seek to a point after the last frame; we drop
+                                * to binary search right away in this case to avoid any wasted
+                                * iterations of proportional search.
+                                */
+                               right_pos = pos;
+                               BINARY_SEARCH_AFTER_ITERATION = 0;
+                       }
+                       else {
+                               /* this can probably only happen if total_samples is unknown and the
+                                * target_sample is past the end of the stream
+                                */
+                               decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR;
+                               return false;
+                       }
+               }
+               /* our write callback will change the state when it gets to the target frame */
+               else if(!decoder->private_->is_seeking/*@@@@@@ && decoder->protected_->state != OggFLAC__STREAM_DECODER_END_OF_STREAM*/) {
+                       break;
+               }
+               else {
+                       this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
+                       FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
+
+                       if (did_a_seek) {
+                               if (this_frame_sample <= target_sample) {
+                                       /* The 'equal' case should not happen, since
+                                        * OggFLAC__stream_decoder_process_single()
+                                        * should recognize that it has hit the
+                                        * target sample and we would exit through
+                                        * the 'break' above.
+                                        */
+                                       FLAC__ASSERT(this_frame_sample != target_sample);
+
+                                       left_sample = this_frame_sample;
+                                       /* sanity check to avoid infinite loop */
+                                       if (left_pos == pos) {
+                                               decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR;
+                                               return false;
+                                       }
+                                       left_pos = pos;
+                               }
+                               else if(this_frame_sample > target_sample) {
+                                       right_sample = this_frame_sample;
+                                       /* sanity check to avoid infinite loop */
+                                       if (right_pos == pos) {
+                                               decoder->protected_->state = OggFLAC__STREAM_DECODER_SEEK_ERROR;
+                                               return false;
+                                       }
+                                       right_pos = pos;
+                               }
+                       }
+               }
+       }
+
+       return true;
+}
+
+FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *super, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super;
+       (void)client_data;
+
+       if(*bytes > 0) {
+               *bytes = (unsigned)fread(buffer, sizeof(FLAC__byte), *bytes, decoder->private_->file);
+               if(ferror(decoder->private_->file))
+                       return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+               else if(*bytes == 0)
+                       return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+               else
+                       return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+       }
+       else
+               return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
+}
+
+FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *super, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super;
+       (void)client_data;
+
+       if(decoder->private_->file == stdin)
+               return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+       else if(fseeko(decoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+       else
+               return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *super, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super;
+       off_t pos;
+       (void)client_data;
+
+       if(decoder->private_->file == stdin) /*@@@@@@ may work for stdin */
+               return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
+       else if((pos = ftello(decoder->private_->file)) < 0)
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+       else {
+               *absolute_byte_offset = (FLAC__uint64)pos;
+               return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+       }
+}
+
+FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *super, FLAC__uint64 *stream_length, void *client_data)
+{
+       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super;
+       struct stat filestats;
+       (void)client_data;
+
+       if(decoder->private_->file == stdin)
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+#ifdef OLD_STAT_WAY //@@@@@@
+       else if(0 == decoder->private_->filename || fstat(fileno(decoder->private_->file), &filestats) != 0)
+#endif
+       else if(fstat(fileno(decoder->private_->file), &filestats) != 0)
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+       else {
+               *stream_length = (FLAC__uint64)filestats.st_size;
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+       }
+}
+
+FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *super, void *client_data)
+{
+       OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder *)super;
+       (void)client_data;
+
+       if(decoder->private_->file == stdin) /*@@@@@@ feof() may work for stdin */
+               return false;
+       return feof(decoder->private_->file)? true : false;
+}
index 1c7c95a..53e35b6 100644 (file)
 #  include <config.h>
 #endif
 
+#if defined _MSC_VER || defined __MINGW32__
+#include <io.h> /* for _setmode() */
+#include <fcntl.h> /* for _O_BINARY */
+#endif
+#if defined __CYGWIN__ || defined __EMX__
+#include <io.h> /* for setmode(), O_BINARY */
+#include <fcntl.h> /* for _O_BINARY */
+#endif
 #include <stdio.h>
 #include <stdlib.h> /* for calloc() */
+#include <string.h> /* for memcpy() */
+#include <sys/types.h> /* for off_t */
+#if defined _MSC_VER || defined __MINGW32__
+/*@@@ [2G limit] hacks for MSVC6 */
+#define fseeko fseek
+#define ftello ftell
+#endif
 #include "FLAC/assert.h"
 #include "OggFLAC/stream_encoder.h"
 #include "protected/stream_encoder.h"
+#include "private/ogg_helper.h"
+
+#ifdef max
+#undef max
+#endif
+#define max(a,b) ((a)>(b)?(a):(b))
 
 /***********************************************************************
  *
@@ -53,6 +74,11 @@ extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEn
 static void set_defaults_(OggFLAC__StreamEncoder *encoder);
 static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
 static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static OggFLAC__StreamEncoderReadStatus file_read_callback_(const OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
+static FILE *get_binary_stdout_();
 
 
 /***********************************************************************
@@ -62,10 +88,24 @@ static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__S
  ***********************************************************************/
 
 typedef struct OggFLAC__StreamEncoderPrivate {
-       OggFLAC__StreamEncoderWriteCallback write_callback;
-       OggFLAC__StreamEncoderMetadataCallback metadata_callback;
+       OggFLAC__StreamEncoderReadCallback read_callback;
+       FLAC__StreamEncoderWriteCallback write_callback;
+       FLAC__StreamEncoderSeekCallback seek_callback;
+       FLAC__StreamEncoderTellCallback tell_callback;
+       FLAC__StreamEncoderMetadataCallback metadata_callback;
+       FLAC__StreamEncoderProgressCallback progress_callback;
        void *client_data;
+#if 0 //@@@@@@
        FLAC__StreamEncoder *FLAC_stream_encoder;
+#endif
+       FLAC__StreamMetadata_SeekTable *seek_table;
+       /* internal vars (all the above are class settings) */
+       unsigned first_seekpoint_to_check;
+       FILE *file;                            /* only used when encoding to a file */
+       FLAC__uint64 bytes_written;
+       FLAC__uint64 samples_written;
+       unsigned frames_written;
+       unsigned total_frames_estimate;
 } OggFLAC__StreamEncoderPrivate;
 
 
@@ -77,12 +117,19 @@ typedef struct OggFLAC__StreamEncoderPrivate {
 
 OggFLAC_API const char * const OggFLAC__StreamEncoderStateString[] = {
        "OggFLAC__STREAM_ENCODER_OK",
+       "OggFLAC__STREAM_ENCODER_UNINITIALIZED",
        "OggFLAC__STREAM_ENCODER_OGG_ERROR",
        "OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR",
-       "OggFLAC__STREAM_ENCODER_INVALID_CALLBACK",
-       "OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
-       "OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
-       "OggFLAC__STREAM_ENCODER_UNINITIALIZED"
+       "OggFLAC__STREAM_ENCODER_CLIENT_ERROR",
+       "OggFLAC__STREAM_ENCODER_IO_ERROR",
+       "OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR"
+};
+
+OggFLAC_API const char * const OggFLAC__treamEncoderReadStatusString[] = {
+       "OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE",
+       "OggFLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM",
+       "OggFLAC__STREAM_ENCODER_READ_STATUS_ABORT",
+       "OggFLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED"
 };
 
 
@@ -94,6 +141,9 @@ OggFLAC_API const char * const OggFLAC__StreamEncoderStateString[] = {
 OggFLAC_API OggFLAC__StreamEncoder *OggFLAC__stream_encoder_new()
 {
        OggFLAC__StreamEncoder *encoder;
+       FLAC__StreamEncoder *parent;
+
+       FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
 
        encoder = (OggFLAC__StreamEncoder*)calloc(1, sizeof(OggFLAC__StreamEncoder));
        if(encoder == 0) {
@@ -113,13 +163,16 @@ OggFLAC_API OggFLAC__StreamEncoder *OggFLAC__stream_encoder_new()
                return 0;
        }
 
-       encoder->private_->FLAC_stream_encoder = FLAC__stream_encoder_new();
-       if(0 == encoder->private_->FLAC_stream_encoder) {
+       parent = FLAC__stream_encoder_new();
+       if(0 == parent) {
                free(encoder->private_);
                free(encoder->protected_);
                free(encoder);
                return 0;
        }
+       encoder->super_ = *parent;
+
+       encoder->private_->file = 0;
 
        set_defaults_(encoder);
 
@@ -133,15 +186,15 @@ OggFLAC_API void OggFLAC__stream_encoder_delete(OggFLAC__StreamEncoder *encoder)
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->protected_);
        FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
 
        (void)OggFLAC__stream_encoder_finish(encoder);
 
-       FLAC__stream_encoder_delete(encoder->private_->FLAC_stream_encoder);
-
        free(encoder->private_);
        free(encoder->protected_);
-       free(encoder);
+       /* don't free(encoder) because FLAC__stream_encoder_delete() will do it */
+
+       /* call superclass destructor last */
+       FLAC__stream_encoder_delete((FLAC__StreamEncoder*)encoder);
 }
 
 
@@ -151,27 +204,126 @@ OggFLAC_API void OggFLAC__stream_encoder_delete(OggFLAC__StreamEncoder *encoder)
  *
  ***********************************************************************/
 
-OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_init(OggFLAC__StreamEncoder *encoder)
+OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_stream(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderReadCallback read_callback, FLAC__StreamEncoderWriteCallback write_callback, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderTellCallback tell_callback, FLAC__StreamEncoderMetadataCallback metadata_callback, void *client_data)
 {
        FLAC__ASSERT(0 != encoder);
 
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
-               return encoder->protected_->state = OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
+
+       if(0 == write_callback || (seek_callback && (0 == read_callback || 0 == tell_callback)))
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
 
-       if(0 == encoder->private_->write_callback || 0 == encoder->private_->metadata_callback)
-               return encoder->protected_->state = OggFLAC__STREAM_ENCODER_INVALID_CALLBACK;
+       /* check seek table before FLAC__stream_encoder_init_stream() does, just to avoid messing up the encoder state for a trivial error */
+       if(0 != encoder->private_->seek_table && !FLAC__format_seektable_is_legal(encoder->private_->seek_table))
+               return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
 
-       if(!OggFLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect))
-                       return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
+       /* set state to OK; from here on, errors are fatal and we'll override the state then */
+       encoder->protected_->state = OggFLAC__STREAM_ENCODER_OK;
+
+       if(!OggFLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect)) {
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
 
-       FLAC__stream_encoder_set_write_callback(encoder->private_->FLAC_stream_encoder, write_callback_);
-       FLAC__stream_encoder_set_metadata_callback(encoder->private_->FLAC_stream_encoder, metadata_callback_);
-       FLAC__stream_encoder_set_client_data(encoder->private_->FLAC_stream_encoder, encoder);
+       encoder->private_->read_callback = read_callback;
+       encoder->private_->write_callback = write_callback;
+       encoder->private_->seek_callback = seek_callback;
+       encoder->private_->tell_callback = tell_callback;
+       encoder->private_->metadata_callback = metadata_callback;
+       encoder->private_->client_data = client_data;
+
+       /*
+        * These must be done before we init the stream encoder because that
+        * calls the write_callback, which uses these values.
+        */
+       encoder->private_->first_seekpoint_to_check = 0;
+       encoder->private_->samples_written = 0;
+       encoder->protected_->streaminfo_offset = 0;
+       encoder->protected_->seektable_offset = 0;
+       encoder->protected_->audio_offset = 0;
+
+       /* we do our own special metadata updating inside Ogg here, so we don't pass in our seek/tell callbacks */
+       if(FLAC__stream_encoder_init_stream((FLAC__StreamEncoder*)encoder, write_callback_, /*seek_callback=*/0, /*tell_callback=*/0, metadata_callback_, /*client_data=*/encoder) != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
 
-       if(FLAC__stream_encoder_init(encoder->private_->FLAC_stream_encoder) != FLAC__STREAM_ENCODER_OK)
-               return encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
+       /*
+        * Initializing the stream encoder writes all the metadata, so we
+        * save the stream offset now.
+        */
+       if(encoder->private_->tell_callback && encoder->private_->tell_callback((FLAC__StreamEncoder*)encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
 
-       return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OK;
+       return FLAC__STREAM_ENCODER_INIT_STATUS_OK;
+}
+
+OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_FILE(OggFLAC__StreamEncoder *encoder, FILE *file, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data)
+{
+       FLAC__StreamEncoderInitStatus init_status;
+
+       FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != file);
+
+       if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
+
+       /*
+        * To make sure that our file does not go unclosed after an error, we
+        * must assign the FILE pointer before any further error can occur in
+        * this routine.
+        */
+       if(file == stdout)
+               file = get_binary_stdout_(); /* just to be safe */
+
+       encoder->private_->file = file;
+
+       encoder->private_->progress_callback = progress_callback;
+       encoder->private_->bytes_written = 0;
+       encoder->private_->samples_written = 0;
+       encoder->private_->frames_written = 0;
+
+       init_status = OggFLAC__stream_encoder_init_stream(encoder, file_read_callback_, file_write_callback_, file_seek_callback_, file_tell_callback_, /*metadata_callback=*/0, client_data);
+       if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
+               /* the above function sets the state for us in case of an error */
+               return init_status;
+       }
+
+       {
+               unsigned blocksize = OggFLAC__stream_encoder_get_blocksize(encoder);
+
+               FLAC__ASSERT(blocksize != 0);
+               encoder->private_->total_frames_estimate = (unsigned)((OggFLAC__stream_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize);
+       }
+
+       return init_status;
+}
+
+OggFLAC_API FLAC__StreamEncoderInitStatus OggFLAC__stream_encoder_init_file(OggFLAC__StreamEncoder *encoder, const char *filename, FLAC__StreamEncoderProgressCallback progress_callback, void *client_data)
+{
+       FILE *file;
+
+       FLAC__ASSERT(0 != encoder);
+
+       /*
+        * To make sure that our file does not go unclosed after an error, we
+        * have to do the same entrance checks here that are later performed
+        * in FLAC__stream_encoder_init_FILE() before the FILE* is assigned.
+        */
+       if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
+
+       file = filename? fopen(filename, "w+b") : stdout;
+
+       if(file == 0) {
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_IO_ERROR;
+               return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
+       }
+
+       return OggFLAC__stream_encoder_init_FILE(encoder, file, progress_callback, client_data);
 }
 
 OggFLAC_API void OggFLAC__stream_encoder_finish(OggFLAC__StreamEncoder *encoder)
@@ -183,9 +335,9 @@ OggFLAC_API void OggFLAC__stream_encoder_finish(OggFLAC__StreamEncoder *encoder)
        if(encoder->protected_->state == OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return;
 
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
 
-       FLAC__stream_encoder_finish(encoder->private_->FLAC_stream_encoder);
+       FLAC__stream_encoder_finish((FLAC__StreamEncoder*)encoder);
 
        OggFLAC__ogg_encoder_aspect_finish(&encoder->protected_->ogg_encoder_aspect);
 
@@ -199,7 +351,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_serial_number(OggFLAC__Stream
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
        OggFLAC__ogg_encoder_aspect_set_serial_number(&encoder->protected_->ogg_encoder_aspect, value);
@@ -211,10 +363,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_verify(OggFLAC__StreamEncoder
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_verify(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_verify((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_streamable_subset(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
@@ -222,10 +374,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_streamable_subset(OggFLAC__St
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_streamable_subset(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_streamable_subset((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_mid_side_stereo(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
@@ -233,10 +385,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_mid_side_stereo(OggFLAC__S
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_do_mid_side_stereo((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_loose_mid_side_stereo(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
@@ -244,10 +396,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_loose_mid_side_stereo(OggFLAC
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_loose_mid_side_stereo((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_channels(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -255,10 +407,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_channels(OggFLAC__StreamEncod
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_channels(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_channels((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_bits_per_sample(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -266,10 +418,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_bits_per_sample(OggFLAC__Stre
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_bits_per_sample((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_sample_rate(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -277,10 +429,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_sample_rate(OggFLAC__StreamEn
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_sample_rate(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_sample_rate((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_blocksize(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -288,10 +440,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_blocksize(OggFLAC__StreamEnco
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_blocksize((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_apodization(OggFLAC__StreamEncoder *encoder, const char *specification)
@@ -299,10 +451,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_apodization(OggFLAC__StreamEn
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_apodization(encoder->private_->FLAC_stream_encoder, specification);
+       return FLAC__stream_encoder_set_apodization((FLAC__StreamEncoder*)encoder, specification);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_lpc_order(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -310,10 +462,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_lpc_order(OggFLAC__Stream
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_max_lpc_order((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_qlp_coeff_precision(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -321,10 +473,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_qlp_coeff_precision(OggFLAC__
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_qlp_coeff_precision((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
@@ -332,10 +484,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(OggF
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_do_qlp_coeff_prec_search((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_escape_coding(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
@@ -343,10 +495,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_escape_coding(OggFLAC__Str
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_do_escape_coding((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_exhaustive_model_search(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
@@ -354,10 +506,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_exhaustive_model_search(Og
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_do_exhaustive_model_search((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_min_residual_partition_order(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -365,10 +517,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_min_residual_partition_order(
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_min_residual_partition_order((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_residual_partition_order(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -376,10 +528,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_residual_partition_order(
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_max_residual_partition_order((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_rice_parameter_search_dist(OggFLAC__StreamEncoder *encoder, unsigned value)
@@ -387,10 +539,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_rice_parameter_search_dist(Og
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_rice_parameter_search_dist((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLAC__StreamEncoder *encoder, FLAC__uint64 value)
@@ -398,10 +550,10 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLA
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_set_total_samples_estimate((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
@@ -409,7 +561,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncod
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+       //@@@@@@superclass;FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
        /* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */
@@ -425,49 +577,24 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncod
                        }
                }
        }
+       if(0 != metadata && num_blocks > 0) {
+               unsigned i;
+               for(i = 0; i < num_blocks; i++) {
+                       /* keep track of any SEEKTABLE block */
+                       if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
+                               encoder->private_->seek_table = &metadata[i]->data.seek_table;
+                               break; /* take only the first one */
+                       }
+               }
+       }
        if(!OggFLAC__ogg_encoder_aspect_set_num_metadata(&encoder->protected_->ogg_encoder_aspect, num_blocks))
                return false;
-       return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks);
-}
-
-OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_write_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderWriteCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->write_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderMetadataCallback value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       FLAC__ASSERT(0 != value);
-       if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->metadata_callback = value;
-       return true;
-}
-
-OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_client_data(OggFLAC__StreamEncoder *encoder, void *value)
-{
-       FLAC__ASSERT(0 != encoder);
-       FLAC__ASSERT(0 != encoder->private_);
-       FLAC__ASSERT(0 != encoder->protected_);
-       if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
-               return false;
-       encoder->private_->client_data = value;
-       return true;
+       return FLAC__stream_encoder_set_metadata((FLAC__StreamEncoder*)encoder, metadata, num_blocks);
 }
 
 /*
  * These three functions are not static, but not publically exposed in
- * include/FLAC/ either.  They are used by the test suite.
+ * include/OggFLAC/ either.  They are used by the test suite.
  */
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_constant_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
 {
@@ -476,7 +603,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_constant_subframes(OggFLA
        FLAC__ASSERT(0 != encoder->protected_);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_disable_constant_subframes(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_disable_constant_subframes((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_fixed_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
@@ -486,7 +613,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_fixed_subframes(OggFLAC__
        FLAC__ASSERT(0 != encoder->protected_);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_disable_fixed_subframes(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_disable_fixed_subframes((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_verbatim_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
@@ -496,7 +623,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_verbatim_subframes(OggFLA
        FLAC__ASSERT(0 != encoder->protected_);
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
                return false;
-       return FLAC__stream_encoder_disable_verbatim_subframes(encoder->private_->FLAC_stream_encoder, value);
+       return FLAC__stream_encoder_disable_verbatim_subframes((FLAC__StreamEncoder*)encoder, value);
 }
 
 OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_get_state(const OggFLAC__StreamEncoder *encoder)
@@ -512,7 +639,7 @@ OggFLAC_API FLAC__StreamEncoderState OggFLAC__stream_encoder_get_FLAC_stream_enc
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_state(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_state((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_encoder_get_verify_decoder_state(const OggFLAC__StreamEncoder *encoder)
@@ -520,7 +647,7 @@ OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_encoder_get_verify_decoder_
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_verify_decoder_state((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API const char *OggFLAC__stream_encoder_get_resolved_state_string(const OggFLAC__StreamEncoder *encoder)
@@ -528,14 +655,14 @@ OggFLAC_API const char *OggFLAC__stream_encoder_get_resolved_state_string(const
        if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR)
                return OggFLAC__StreamEncoderStateString[encoder->protected_->state];
        else
-               return FLAC__stream_encoder_get_resolved_state_string(encoder->private_->FLAC_stream_encoder);
+               return FLAC__stream_encoder_get_resolved_state_string((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API void OggFLAC__stream_encoder_get_verify_decoder_error_stats(const OggFLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
 {
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
-       FLAC__stream_encoder_get_verify_decoder_error_stats(encoder->private_->FLAC_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
+       FLAC__stream_encoder_get_verify_decoder_error_stats((FLAC__StreamEncoder*)encoder, absolute_sample, frame_number, channel, sample, expected, got);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_verify(const OggFLAC__StreamEncoder *encoder)
@@ -543,7 +670,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_verify(const OggFLAC__StreamE
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_verify(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_verify((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_streamable_subset(const OggFLAC__StreamEncoder *encoder)
@@ -551,7 +678,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_streamable_subset(const OggFL
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_streamable_subset(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_streamable_subset((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_mid_side_stereo(const OggFLAC__StreamEncoder *encoder)
@@ -559,7 +686,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_mid_side_stereo(const OggF
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_do_mid_side_stereo((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_loose_mid_side_stereo(const OggFLAC__StreamEncoder *encoder)
@@ -567,7 +694,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_loose_mid_side_stereo(const O
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_loose_mid_side_stereo((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_channels(const OggFLAC__StreamEncoder *encoder)
@@ -575,7 +702,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_channels(const OggFLAC__StreamE
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_channels(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_channels((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_bits_per_sample(const OggFLAC__StreamEncoder *encoder)
@@ -583,7 +710,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_bits_per_sample(const OggFLAC__
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_bits_per_sample((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_sample_rate(const OggFLAC__StreamEncoder *encoder)
@@ -591,7 +718,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_sample_rate(const OggFLAC__Stre
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_sample_rate(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_sample_rate((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_blocksize(const OggFLAC__StreamEncoder *encoder)
@@ -599,7 +726,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_blocksize(const OggFLAC__Stream
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_blocksize((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_lpc_order(const OggFLAC__StreamEncoder *encoder)
@@ -607,7 +734,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_lpc_order(const OggFLAC__St
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_max_lpc_order((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_qlp_coeff_precision(const OggFLAC__StreamEncoder *encoder)
@@ -615,7 +742,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_qlp_coeff_precision(const OggFL
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_qlp_coeff_precision((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__StreamEncoder *encoder)
@@ -623,7 +750,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_qlp_coeff_prec_search(cons
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_do_qlp_coeff_prec_search((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_escape_coding(const OggFLAC__StreamEncoder *encoder)
@@ -631,7 +758,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_escape_coding(const OggFLA
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_do_escape_coding((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_exhaustive_model_search(const OggFLAC__StreamEncoder *encoder)
@@ -639,7 +766,7 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_exhaustive_model_search(co
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_do_exhaustive_model_search((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_min_residual_partition_order(const OggFLAC__StreamEncoder *encoder)
@@ -647,7 +774,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_min_residual_partition_order(co
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_min_residual_partition_order((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_residual_partition_order(const OggFLAC__StreamEncoder *encoder)
@@ -655,7 +782,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_residual_partition_order(co
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_max_residual_partition_order((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API unsigned OggFLAC__stream_encoder_get_rice_parameter_search_dist(const OggFLAC__StreamEncoder *encoder)
@@ -663,7 +790,7 @@ OggFLAC_API unsigned OggFLAC__stream_encoder_get_rice_parameter_search_dist(cons
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_rice_parameter_search_dist((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__uint64 OggFLAC__stream_encoder_get_total_samples_estimate(const OggFLAC__StreamEncoder *encoder)
@@ -671,7 +798,7 @@ OggFLAC_API FLAC__uint64 OggFLAC__stream_encoder_get_total_samples_estimate(cons
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder);
+       return FLAC__stream_encoder_get_total_samples_estimate((FLAC__StreamEncoder*)encoder);
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process(OggFLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
@@ -679,7 +806,12 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process(OggFLAC__StreamEncoder *e
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_process(encoder->private_->FLAC_stream_encoder, buffer, samples);
+       if(!FLAC__stream_encoder_process((FLAC__StreamEncoder*)encoder, buffer, samples)) {
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
+               return false;
+       }
+       else
+               return true;
 }
 
 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process_interleaved(OggFLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
@@ -687,7 +819,12 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process_interleaved(OggFLAC__Stre
        FLAC__ASSERT(0 != encoder);
        FLAC__ASSERT(0 != encoder->private_);
        FLAC__ASSERT(0 != encoder->protected_);
-       return FLAC__stream_encoder_process_interleaved(encoder->private_->FLAC_stream_encoder, buffer, samples);
+       if(!FLAC__stream_encoder_process_interleaved((FLAC__StreamEncoder*)encoder, buffer, samples)) {
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
+               return false;
+       }
+       else
+               return true;
 }
 
 /***********************************************************************
@@ -699,30 +836,376 @@ OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process_interleaved(OggFLAC__Stre
 void set_defaults_(OggFLAC__StreamEncoder *encoder)
 {
        FLAC__ASSERT(0 != encoder);
+       FLAC__ASSERT(0 != encoder->private_);
+       FLAC__ASSERT(0 != encoder->protected_);
 
+       encoder->private_->read_callback = 0;
        encoder->private_->write_callback = 0;
+       encoder->private_->seek_callback = 0;
+       encoder->private_->tell_callback = 0;
        encoder->private_->metadata_callback = 0;
+       encoder->private_->progress_callback = 0;
        encoder->private_->client_data = 0;
+
+       encoder->private_->seek_table = 0;
+
        OggFLAC__ogg_encoder_aspect_set_defaults(&encoder->protected_->ogg_encoder_aspect);
 }
 
-FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
+FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *super, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
 {
-       OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)client_data;
-       const FLAC__uint64 total_samples_estimate = FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder);
+       OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super;
+       FLAC__StreamEncoderWriteStatus status;
+       FLAC__uint64 output_position;
+
+       (void)client_data; /* silence compiler warning about unused parameter */
+
+       /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */
+       if(encoder->private_->tell_callback && encoder->private_->tell_callback((FLAC__StreamEncoder*)encoder, &output_position, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) {
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
+               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
+       }
+
+       /*
+        * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets.
+        */
+       if(samples == 0) {
+               FLAC__MetadataType type = (buffer[0] & 0x7f);
+               if(type == FLAC__METADATA_TYPE_STREAMINFO)
+                       encoder->protected_->streaminfo_offset = output_position;
+               else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0)
+                       encoder->protected_->seektable_offset = output_position;
+       }
+
+       /*
+        * Mark the current seek point if hit (if audio_offset == 0 that
+        * means we're still writing metadata and haven't hit the first
+        * frame yet)
+        */
+       if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) {
+               const unsigned blocksize = FLAC__stream_encoder_get_blocksize((FLAC__StreamEncoder*)encoder);
+               const FLAC__uint64 frame_first_sample = encoder->private_->samples_written;
+               const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
+               FLAC__uint64 test_sample;
+               unsigned i;
+               for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) {
+                       test_sample = encoder->private_->seek_table->points[i].sample_number;
+                       if(test_sample > frame_last_sample) {
+                               break;
+                       }
+                       else if(test_sample >= frame_first_sample) {
+                               encoder->private_->seek_table->points[i].sample_number = frame_first_sample;
+                               encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset;
+                               encoder->private_->seek_table->points[i].frame_samples = blocksize;
+                               encoder->private_->first_seekpoint_to_check++;
+                               /* DO NOT: "break;" and here's why:
+                                * The seektable template may contain more than one target
+                                * sample for any given frame; we will keep looping, generating
+                                * duplicate seekpoints for them, and we'll clean it up later,
+                                * just before writing the seektable back to the metadata.
+                                */
+                       }
+                       else {
+                               encoder->private_->first_seekpoint_to_check++;
+                       }
+               }
+       }
 
-       (void)unused;
-       FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
+       status = OggFLAC__ogg_encoder_aspect_write_callback_wrapper(&encoder->protected_->ogg_encoder_aspect, FLAC__stream_encoder_get_total_samples_estimate((FLAC__StreamEncoder*)encoder), buffer, bytes, samples, current_frame, (OggFLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback, encoder, encoder->private_->client_data);
 
-       return OggFLAC__ogg_encoder_aspect_write_callback_wrapper(&encoder->protected_->ogg_encoder_aspect, total_samples_estimate, buffer, bytes, samples, current_frame, (OggFLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback, encoder, encoder->private_->client_data);
+       if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
+               encoder->private_->samples_written += samples;
+       else
+               encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
+
+       return status;
 }
 
-void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
+void metadata_callback_(const FLAC__StreamEncoder *super, const FLAC__StreamMetadata *metadata, void *client_data)
 {
-       OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)client_data;
+       OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super;
+       FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)];
+       const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
+       const unsigned min_framesize = metadata->data.stream_info.min_framesize;
+       const unsigned max_framesize = metadata->data.stream_info.max_framesize;
+       ogg_page page;
+
+       FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
+
+       /* We get called by the stream encoder when the encoding process
+        * has finished so that we can update the STREAMINFO and SEEKTABLE
+        * blocks.
+        */
+
+       (void)client_data; /* silence compiler warning about unused parameter */
+
+       /* All this is based on intimate knowledge of the stream header
+        * layout, but a change to the header format that would break this
+        * would also break all streams encoded in the previous format.
+        */
+
+       /**
+        ** Write STREAMINFO stats
+        **/
+       simple_ogg_page__init(&page);
+       if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) {
+               simple_ogg_page__clear(&page);
+               return; /* state already set */
+       }
 
-       (void)unused;
-       FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
+       /*
+        * Write MD5 signature
+        */
+       {
+               const unsigned md5_offset =
+                       FLAC__STREAM_METADATA_HEADER_LENGTH +
+                       (
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
+                       ) / 8;
+
+               if(md5_offset + 16 > (unsigned)page.body_len) {
+                       encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
+                       simple_ogg_page__clear(&page);
+                       return;
+               }
+               memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16);
+       }
+
+       /*
+        * Write total samples
+        */
+       {
+               const unsigned total_samples_byte_offset =
+                       FLAC__STREAM_METADATA_HEADER_LENGTH +
+                       (
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
+                               - 4
+                       ) / 8;
+
+               if(total_samples_byte_offset + 5 > (unsigned)page.body_len) {
+                       encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
+                       simple_ogg_page__clear(&page);
+                       return;
+               }
+               b[0] = (FLAC__byte)page.body[total_samples_byte_offset] & 0xF0;
+               b[0] |= (FLAC__byte)((samples >> 32) & 0x0F);
+               b[1] = (FLAC__byte)((samples >> 24) & 0xFF);
+               b[2] = (FLAC__byte)((samples >> 16) & 0xFF);
+               b[3] = (FLAC__byte)((samples >> 8) & 0xFF);
+               b[4] = (FLAC__byte)(samples & 0xFF);
+               memcpy(page.body + total_samples_byte_offset, b, 5);
+       }
+
+       /*
+        * Write min/max framesize
+        */
+       {
+               const unsigned min_framesize_offset =
+                       FLAC__STREAM_METADATA_HEADER_LENGTH +
+                       (
+                               FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
+                               FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
+                       ) / 8;
+
+               if(min_framesize_offset + 6 > (unsigned)page.body_len) {
+                       encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
+                       simple_ogg_page__clear(&page);
+                       return;
+               }
+               b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF);
+               b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF);
+               b[2] = (FLAC__byte)(min_framesize & 0xFF);
+               b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF);
+               b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF);
+               b[5] = (FLAC__byte)(max_framesize & 0xFF);
+               memcpy(page.body + min_framesize_offset, b, 6);
+       }
+       if(!simple_ogg_page__set_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) {
+               simple_ogg_page__clear(&page);
+               return; /* state already set */
+       }
+       simple_ogg_page__clear(&page);
+
+       /*
+        * Write seektable
+        */
+       if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) {
+               unsigned i;
+               FLAC__byte *p;
+
+               FLAC__format_seektable_sort(encoder->private_->seek_table);
+
+               FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table));
+
+               simple_ogg_page__init(&page);
+               if(!simple_ogg_page__get_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) {
+                       simple_ogg_page__clear(&page);
+                       return; /* state already set */
+               }
+
+               if(FLAC__STREAM_METADATA_HEADER_LENGTH + (18*encoder->private_->seek_table->num_points) > (unsigned)page.body_len) {
+                       encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
+                       simple_ogg_page__clear(&page);
+                       return;
+               }
+
+               for(i = 0, p = page.body + FLAC__STREAM_METADATA_HEADER_LENGTH; i < encoder->private_->seek_table->num_points; i++, p += 18) {
+                       FLAC__uint64 xx;
+                       unsigned x;
+                       xx = encoder->private_->seek_table->points[i].sample_number;
+                       b[7] = (FLAC__byte)xx; xx >>= 8;
+                       b[6] = (FLAC__byte)xx; xx >>= 8;
+                       b[5] = (FLAC__byte)xx; xx >>= 8;
+                       b[4] = (FLAC__byte)xx; xx >>= 8;
+                       b[3] = (FLAC__byte)xx; xx >>= 8;
+                       b[2] = (FLAC__byte)xx; xx >>= 8;
+                       b[1] = (FLAC__byte)xx; xx >>= 8;
+                       b[0] = (FLAC__byte)xx; xx >>= 8;
+                       xx = encoder->private_->seek_table->points[i].stream_offset;
+                       b[15] = (FLAC__byte)xx; xx >>= 8;
+                       b[14] = (FLAC__byte)xx; xx >>= 8;
+                       b[13] = (FLAC__byte)xx; xx >>= 8;
+                       b[12] = (FLAC__byte)xx; xx >>= 8;
+                       b[11] = (FLAC__byte)xx; xx >>= 8;
+                       b[10] = (FLAC__byte)xx; xx >>= 8;
+                       b[9] = (FLAC__byte)xx; xx >>= 8;
+                       b[8] = (FLAC__byte)xx; xx >>= 8;
+                       x = encoder->private_->seek_table->points[i].frame_samples;
+                       b[17] = (FLAC__byte)x; x >>= 8;
+                       b[16] = (FLAC__byte)x; x >>= 8;
+                       if(encoder->private_->write_callback((FLAC__StreamEncoder*)encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
+                               encoder->protected_->state = OggFLAC__STREAM_ENCODER_CLIENT_ERROR;
+                               simple_ogg_page__clear(&page);
+                               return;
+                       }
+                       memcpy(p, b, 18);
+               }
+
+               if(!simple_ogg_page__set_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) {
+                       simple_ogg_page__clear(&page);
+                       return; /* state already set */
+               }
+               simple_ogg_page__clear(&page);
+       }
+
+       if(encoder->private_->metadata_callback)
+               encoder->private_->metadata_callback((FLAC__StreamEncoder*)encoder, metadata, client_data);
+}
+
+OggFLAC__StreamEncoderReadStatus file_read_callback_(const OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+       (void)client_data;
+
+       *bytes = (unsigned)fread(buffer, 1, *bytes, encoder->private_->file);
+       if (*bytes == 0) {
+               if (feof(encoder->private_->file))
+                       return OggFLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM;
+               else if (ferror(encoder->private_->file))
+                       return OggFLAC__STREAM_ENCODER_READ_STATUS_ABORT;
+       }
+       return OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE;
+}
+
+FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *super, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+       OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super;
+
+       (void)client_data;
+
+       if(fseeko(encoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
+               return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
+       else
+               return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+}
+
+FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *super, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+       OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super;
+       off_t offset;
+
+       (void)client_data;
+
+       offset = ftello(encoder->private_->file);
+
+       if(offset < 0) {
+               return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
+       }
+       else {
+               *absolute_byte_offset = (FLAC__uint64)offset;
+               return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+       }
+}
+
+#ifdef FLAC__VALGRIND_TESTING
+static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+       size_t ret = fwrite(ptr, size, nmemb, stream);
+       if(!ferror(stream))
+               fflush(stream);
+       return ret;
+}
+#else
+#define local__fwrite fwrite
+#endif
+
+FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *super, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
+{
+       OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)super;
+
+       (void)client_data;
+
+       if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, encoder->private_->file) == bytes) {
+               encoder->private_->bytes_written += bytes;
+               encoder->private_->samples_written += samples;
+               /* we keep a high watermark on the number of frames written because
+                * when the encoder goes back to write metadata, 'current_frame'
+                * will drop back to 0.
+                */
+               encoder->private_->frames_written = max(encoder->private_->frames_written, current_frame+1);
+               /*@@@ We would like to add an '&& samples > 0' to the if
+                * clause here but currently because of the nature of our Ogg
+                * writing implementation, 'samples' is always 0 (see
+                * ogg_encoder_aspect.c).  The downside is extra progress
+                * callbacks.
+                */
+               if(0 != encoder->private_->progress_callback /*@@@ && samples > 0 */)
+                       encoder->private_->progress_callback((FLAC__StreamEncoder*)encoder, encoder->private_->bytes_written, encoder->private_->samples_written, encoder->private_->frames_written, encoder->private_->total_frames_estimate, encoder->private_->client_data);
+               return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+       }
+       else
+               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
+}
+
+/*
+ * This will forcibly set stdout to binary mode (for OSes that require it)
+ */
+FILE *get_binary_stdout_()
+{
+       /* if something breaks here it is probably due to the presence or
+        * absence of an underscore before the identifiers 'setmode',
+        * 'fileno', and/or 'O_BINARY'; check your system header files.
+        */
+#if defined _MSC_VER || defined __MINGW32__
+       _setmode(_fileno(stdout), _O_BINARY);
+#elif defined __CYGWIN__
+       /* almost certainly not needed for any modern Cygwin, but let's be safe... */
+       setmode(_fileno(stdout), _O_BINARY);
+#elif defined __EMX__
+       setmode(fileno(stdout), O_BINARY);
+#endif
 
-       encoder->private_->metadata_callback(encoder, metadata, encoder->private_->client_data);
+       return stdout;
 }
index 51ba63e..4af5fbf 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "utils.h"
 #include "FLAC/assert.h"
-#include "FLAC/file_decoder.h"
+#include "FLAC/stream_decoder.h"
 #include "FLAC/metadata.h"
 #include "share/grabbag.h"
 
@@ -103,14 +103,14 @@ typedef struct {
        FLAC__StreamDecoderErrorStatus error_status;
 } ClientData;
 
-static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
        ClientData *cd = (ClientData*)client_data;
 
        (void)buffer;
        FLAC__ASSERT(0 != cd);
 
-       if(!cd->error_occurred && cd->seektable_template->num_points > 0) {
+       if(!cd->error_occurred) {
                const unsigned blocksize = frame->header.blocksize;
                const FLAC__uint64 frame_first_sample = cd->samples_written;
                const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
@@ -138,7 +138,7 @@ static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *d
                        }
                }
                cd->samples_written += blocksize;
-               if(!FLAC__file_decoder_get_decode_position(decoder, &cd->last_offset))
+               if(!FLAC__stream_decoder_get_decode_position(decoder, &cd->last_offset))
                        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
                return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
        }
@@ -146,13 +146,7 @@ static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *d
                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
 }
 
-static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       (void)decoder, (void)metadata, (void)client_data;
-       FLAC__ASSERT(0); /* we asked to skip all metadata */
-}
-
-static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
        ClientData *cd = (ClientData*)client_data;
 
@@ -167,7 +161,7 @@ static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecode
 
 FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata *block, FLAC__bool *needs_write)
 {
-       FLAC__FileDecoder *decoder;
+       FLAC__StreamDecoder *decoder;
        ClientData client_data;
        FLAC__bool ok = true;
 
@@ -180,39 +174,34 @@ FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata
        client_data.first_seekpoint_to_check = 0;
        client_data.error_occurred = false;
 
-       decoder = FLAC__file_decoder_new();
+       decoder = FLAC__stream_decoder_new();
 
        if(0 == decoder) {
                fprintf(stderr, "%s: ERROR (--add-seekpoint) creating the decoder instance\n", filename);
                return false;
        }
 
-       FLAC__file_decoder_set_md5_checking(decoder, false);
-       FLAC__file_decoder_set_filename(decoder, filename);
-       FLAC__file_decoder_set_metadata_ignore_all(decoder);
-       FLAC__file_decoder_set_write_callback(decoder, write_callback_);
-       FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
-       FLAC__file_decoder_set_error_callback(decoder, error_callback_);
-       FLAC__file_decoder_set_client_data(decoder, &client_data);
+       FLAC__stream_decoder_set_md5_checking(decoder, false);
+       FLAC__stream_decoder_set_metadata_ignore_all(decoder);
 
-       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
-               fprintf(stderr, "%s: ERROR (--add-seekpoint) initializing the decoder instance (%s)\n", filename, FLAC__file_decoder_get_resolved_state_string(decoder));
+       if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, /*metadata_callback=*/0, error_callback_, &client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+               fprintf(stderr, "%s: ERROR (--add-seekpoint) initializing the decoder instance (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder));
                ok = false;
        }
 
-       if(ok && !FLAC__file_decoder_process_until_end_of_metadata(decoder)) {
-               fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__file_decoder_get_resolved_state_string(decoder));
+       if(ok && !FLAC__stream_decoder_process_until_end_of_metadata(decoder)) {
+               fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder));
                ok = false;
        }
 
-       if(ok && !FLAC__file_decoder_get_decode_position(decoder, &client_data.audio_offset)) {
+       if(ok && !FLAC__stream_decoder_get_decode_position(decoder, &client_data.audio_offset)) {
                fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file\n", filename);
                ok = false;
        }
        client_data.last_offset = client_data.audio_offset;
 
-       if(ok && !FLAC__file_decoder_process_until_end_of_file(decoder)) {
-               fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__file_decoder_get_resolved_state_string(decoder));
+       if(ok && !FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
+               fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder));
                ok = false;
        }
 
@@ -222,6 +211,6 @@ FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata
        }
 
        *needs_write = true;
-       FLAC__file_decoder_delete(decoder);
+       FLAC__stream_decoder_delete(decoder);
        return ok;
 }
index 48af5f3..0db37f1 100644 (file)
@@ -35,9 +35,9 @@ static In_Module mod_;                      /* the input module (declared near t
 static char lastfn_[MAX_PATH];              /* currently playing file (used for getting info on the current file) */\r
 flac_config_t flac_cfg;\r
 \r
-static file_info_struct file_info_;\r
+static stream_data_struct stream_data_;\r
 static int paused;\r
-static FLAC__FileDecoder *decoder_;\r
+static FLAC__StreamDecoder *decoder_;\r
 static char sample_buffer_[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS * (24/8) * 2];\r
 /* (24/8) for max bytes per sample, and 2 for DSPs */\r
 \r
@@ -50,7 +50,7 @@ static DWORD WINAPI DecodeThread(void *b);  /* the decode thread procedure */
 \r
 static void init()\r
 {\r
-       decoder_ = FLAC__file_decoder_new();\r
+       decoder_ = FLAC__stream_decoder_new();\r
        strcpy(lastfn_, "");\r
 \r
        InitConfig();\r
@@ -81,11 +81,11 @@ static int play(char *fn)
        if (decoder_ == 0) return 1;\r
        if (!(filesize = FileSize(fn))) return -1;\r
        /* init decoder */\r
-       if (!FLAC_plugin__decoder_init(decoder_, fn, filesize, &file_info_, &flac_cfg.output))\r
+       if (!FLAC_plugin__decoder_init(decoder_, fn, filesize, &stream_data_, &flac_cfg.output))\r
                return 1;\r
        strcpy(lastfn_, fn);\r
        /* open output */\r
-       maxlatency = mod_.outMod->Open(file_info_.sample_rate, file_info_.channels, file_info_.output_bits_per_sample, -1, -1);\r
+       maxlatency = mod_.outMod->Open(stream_data_.sample_rate, stream_data_.channels, stream_data_.output_bits_per_sample, -1, -1);\r
        if (maxlatency < 0)\r
        {\r
                FLAC_plugin__decoder_finish(decoder_);\r
@@ -95,10 +95,10 @@ static int play(char *fn)
        mod_.outMod->SetVolume(-666);\r
        mod_.outMod->SetPan(0);\r
        /* initialize vis stuff */\r
-       mod_.SAVSAInit(maxlatency, file_info_.sample_rate);\r
-       mod_.VSASetInfo(file_info_.sample_rate, file_info_.channels);\r
+       mod_.SAVSAInit(maxlatency, stream_data_.sample_rate);\r
+       mod_.VSASetInfo(stream_data_.sample_rate, stream_data_.channels);\r
        /* set info */\r
-       mod_.SetInfo(file_info_.average_bps, file_info_.sample_rate/1000, file_info_.channels, 1);\r
+       mod_.SetInfo(stream_data_.average_bps, stream_data_.sample_rate/1000, stream_data_.channels, 1);\r
        /* start playing thread */\r
        paused = 0;\r
        thread_handle = CreateThread(NULL, 0, DecodeThread, NULL, 0, &thread_id);\r
@@ -111,7 +111,7 @@ static void stop()
 {\r
        if (thread_handle)\r
        {\r
-               file_info_.is_playing = false;\r
+               stream_data_.is_playing = false;\r
                if (WaitForSingleObject(thread_handle, 2000) == WAIT_TIMEOUT)\r
                {\r
                        FLAC_plugin__show_error("Error while stopping decoding thread.");\r
@@ -149,7 +149,7 @@ static int ispaused()
 \r
 static int getlength()\r
 {\r
-       return file_info_.length_in_msec;\r
+       return stream_data_.length_in_msec;\r
 }\r
 \r
 static int getoutputtime()\r
@@ -159,7 +159,7 @@ static int getoutputtime()
 \r
 static void setoutputtime(int time_in_ms)\r
 {\r
-       file_info_.seek_to = time_in_ms;\r
+       stream_data_.seek_to = time_in_ms;\r
 }\r
 \r
 static void setvolume(int volume)\r
@@ -214,22 +214,22 @@ static void do_vis(char *data, int nch, int resolution, int position, unsigned s
 \r
 static DWORD WINAPI DecodeThread(void *unused)\r
 {\r
-       const unsigned channels = file_info_.channels;\r
-       const unsigned bits_per_sample = file_info_.bits_per_sample;\r
-       const unsigned target_bps = file_info_.output_bits_per_sample;\r
-       const unsigned sample_rate = file_info_.sample_rate;\r
+       const unsigned channels = stream_data_.channels;\r
+       const unsigned bits_per_sample = stream_data_.bits_per_sample;\r
+       const unsigned target_bps = stream_data_.output_bits_per_sample;\r
+       const unsigned sample_rate = stream_data_.sample_rate;\r
        const unsigned fact = channels * (target_bps/8);\r
 \r
-       while (file_info_.is_playing)\r
+       while (stream_data_.is_playing)\r
        {\r
                /* seek needed */\r
-               if (file_info_.seek_to != -1)\r
+               if (stream_data_.seek_to != -1)\r
                {\r
-                       const int pos = FLAC_plugin__seek(decoder_, &file_info_);\r
+                       const int pos = FLAC_plugin__seek(decoder_, &stream_data_);\r
                        if (pos != -1) mod_.outMod->Flush(pos);\r
                }\r
                /* stream ended */\r
-               else if (file_info_.eof)\r
+               else if (stream_data_.eof)\r
                {\r
                        if (!mod_.outMod->IsPlaying())\r
                        {\r
@@ -242,7 +242,7 @@ static DWORD WINAPI DecodeThread(void *unused)
                else\r
                {\r
                        /* decode samples */\r
-                       int bytes = FLAC_plugin__decode(decoder_, &file_info_, sample_buffer_);\r
+                       int bytes = FLAC_plugin__decode(decoder_, &stream_data_, sample_buffer_);\r
                        const int n = bytes / fact;\r
                        /* visualization */\r
                        do_vis(sample_buffer_, channels, target_bps, mod_.outMod->GetWrittenTime(), n);\r
@@ -250,15 +250,15 @@ static DWORD WINAPI DecodeThread(void *unused)
                        if (mod_.dsp_isactive())\r
                                bytes = mod_.dsp_dosamples((short*)sample_buffer_, n, target_bps, channels, sample_rate) * fact;\r
                        /* output */\r
-                       while (mod_.outMod->CanWrite()<bytes && file_info_.is_playing && file_info_.seek_to==-1)\r
+                       while (mod_.outMod->CanWrite()<bytes && stream_data_.is_playing && stream_data_.seek_to==-1)\r
                                Sleep(20);\r
-                       if (file_info_.is_playing && file_info_.seek_to==-1)\r
+                       if (stream_data_.is_playing && stream_data_.seek_to==-1)\r
                                mod_.outMod->Write(sample_buffer_, bytes);\r
                        /* show bitrate */\r
                        if (flac_cfg.display.show_bps)\r
                        {\r
-                               const int rate = FLAC_plugin__get_rate(mod_.outMod->GetWrittenTime(), mod_.outMod->GetOutputTime(), &file_info_);\r
-                               if (rate) mod_.SetInfo(rate/1000, file_info_.sample_rate/1000, file_info_.channels, 1);\r
+                               const int rate = FLAC_plugin__get_rate(mod_.outMod->GetWrittenTime(), mod_.outMod->GetOutputTime(), &stream_data_);\r
+                               if (rate) mod_.SetInfo(rate/1000, stream_data_.sample_rate/1000, stream_data_.channels, 1);\r
                        }\r
                }\r
        }\r
@@ -334,7 +334,7 @@ static void getfileinfo(char *filename, char *title, int *length_in_msec)
        if (!filename || !*filename) {\r
                filename = lastfn_;\r
                if (length_in_msec) {\r
-                       *length_in_msec = file_info_.length_in_msec;\r
+                       *length_in_msec = stream_data_.length_in_msec;\r
                        length_in_msec = 0;    /* force skip in following code */\r
                }\r
        }\r
index 78965e5..c2f2389 100644 (file)
@@ -39,15 +39,15 @@ static FLAC__int64 decode_position, decode_position_last;
  *  callbacks\r
  */\r
 \r
-static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)\r
+static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)\r
 {\r
-       file_info_struct *file_info = (file_info_struct*)client_data;\r
-       const unsigned channels = file_info->channels, wide_samples = frame->header.blocksize;\r
+       stream_data_struct *stream_data = (stream_data_struct*)client_data;\r
+       const unsigned channels = stream_data->channels, wide_samples = frame->header.blocksize;\r
        unsigned channel;\r
 \r
        (void)decoder;\r
 \r
-       if (file_info->abort_flag)\r
+       if (stream_data->abort_flag)\r
                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;\r
 \r
        for (channel = 0; channel < channels; channel++)\r
@@ -58,31 +58,31 @@ static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *de
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;\r
 }\r
 \r
-static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)\r
+static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)\r
 {\r
-       file_info_struct *file_info = (file_info_struct*)client_data;\r
+       stream_data_struct *stream_data = (stream_data_struct*)client_data;\r
        (void)decoder;\r
 \r
        if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)\r
        {\r
-               file_info->total_samples = metadata->data.stream_info.total_samples;\r
-               file_info->bits_per_sample = metadata->data.stream_info.bits_per_sample;\r
-               file_info->channels = metadata->data.stream_info.channels;\r
-               file_info->sample_rate = metadata->data.stream_info.sample_rate;\r
+               stream_data->total_samples = metadata->data.stream_info.total_samples;\r
+               stream_data->bits_per_sample = metadata->data.stream_info.bits_per_sample;\r
+               stream_data->channels = metadata->data.stream_info.channels;\r
+               stream_data->sample_rate = metadata->data.stream_info.sample_rate;\r
 \r
-               if (file_info->bits_per_sample!=8 && file_info->bits_per_sample!=16 && file_info->bits_per_sample!=24)\r
+               if (stream_data->bits_per_sample!=8 && stream_data->bits_per_sample!=16 && stream_data->bits_per_sample!=24)\r
                {\r
                        FLAC_plugin__show_error("This plugin can only handle 8/16/24-bit samples.");\r
-                       file_info->abort_flag = true;\r
+                       stream_data->abort_flag = true;\r
                        return;\r
                }\r
 \r
                {\r
                        /* with VC++ you have to spoon feed it the casting from uint64->int64->double */\r
-                       FLAC__uint64 l = (FLAC__uint64)((double)(FLAC__int64)file_info->total_samples / (double)file_info->sample_rate * 1000.0 + 0.5);\r
+                       FLAC__uint64 l = (FLAC__uint64)((double)(FLAC__int64)stream_data->total_samples / (double)stream_data->sample_rate * 1000.0 + 0.5);\r
                        if (l > INT_MAX)\r
                                l = INT_MAX;\r
-                       file_info->length_in_msec = (int)l;\r
+                       stream_data->length_in_msec = (int)l;\r
                }\r
        }\r
        else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)\r
@@ -90,71 +90,68 @@ static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__Stre
                double gain, peak;\r
                if (grabbag__replaygain_load_from_vorbiscomment(metadata, cfg.replaygain.album_mode, /*strict=*/false, &gain, &peak))\r
                {\r
-                       file_info->has_replaygain = true;\r
-                       file_info->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)cfg.replaygain.preamp, !cfg.replaygain.hard_limit);\r
+                       stream_data->has_replaygain = true;\r
+                       stream_data->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)cfg.replaygain.preamp, !cfg.replaygain.hard_limit);\r
                }\r
        }\r
 }\r
 \r
-static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)\r
+static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)\r
 {\r
-       file_info_struct *file_info = (file_info_struct*)client_data;\r
+       stream_data_struct *stream_data = (stream_data_struct*)client_data;\r
        (void)decoder;\r
 \r
        if (cfg.misc.stop_err || status!=FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)\r
-               file_info->abort_flag = true;\r
+               stream_data->abort_flag = true;\r
 }\r
 \r
 /*\r
  *  init/delete\r
  */\r
 \r
-FLAC__bool FLAC_plugin__decoder_init(FLAC__FileDecoder *decoder, const char *filename, FLAC__int64 filesize, file_info_struct *file_info, output_config_t *config)\r
+FLAC__bool FLAC_plugin__decoder_init(FLAC__StreamDecoder *decoder, const char *filename, FLAC__int64 filesize, stream_data_struct *stream_data, output_config_t *config)\r
 {\r
+       FLAC__StreamDecoderInitStatus init_status;\r
+\r
        FLAC__ASSERT(decoder);\r
        FLAC_plugin__decoder_finish(decoder);\r
        /* init decoder */\r
-       FLAC__file_decoder_set_md5_checking(decoder, false);\r
-       FLAC__file_decoder_set_filename(decoder, filename);\r
-       FLAC__file_decoder_set_metadata_ignore_all(decoder);\r
-       FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);\r
-       FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);\r
-       FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);\r
-       FLAC__file_decoder_set_write_callback(decoder, write_callback);\r
-       FLAC__file_decoder_set_error_callback(decoder, error_callback);\r
-       FLAC__file_decoder_set_client_data(decoder, file_info);\r
-\r
-       if (FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)\r
+       FLAC__stream_decoder_set_md5_checking(decoder, false);\r
+       FLAC__stream_decoder_set_metadata_ignore_all(decoder);\r
+       FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);\r
+       FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);\r
+\r
+       if ((init_status = FLAC__stream_decoder_init_file(decoder, filename, write_callback, metadata_callback, error_callback, /*client_data=*/stream_data)) != FLAC__STREAM_DECODER_INIT_STATUS_OK)\r
        {\r
-               FLAC_plugin__show_error("Error while initializing decoder (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);\r
+               FLAC_plugin__show_error("Error while initializing decoder (%s [%s]).", FLAC__StreamDecoderInitStatusString[init_status], FLAC__stream_decoder_get_resolved_state_string(decoder));\r
                return false;\r
        }\r
        /* process */\r
        cfg = *config;\r
        wide_samples_in_reservoir_ = 0;\r
-       file_info->is_playing = false;\r
-       file_info->abort_flag = false;\r
-       file_info->has_replaygain = false;\r
+       stream_data->is_playing = false;\r
+       stream_data->abort_flag = false;\r
+       stream_data->has_replaygain = false;\r
 \r
-       if (!FLAC__file_decoder_process_until_end_of_metadata(decoder))\r
+       if (!FLAC__stream_decoder_process_until_end_of_metadata(decoder))\r
        {\r
-               FLAC_plugin__show_error("Error while processing metadata (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);\r
+               FLAC_plugin__show_error("Error while processing metadata (%s).", FLAC__stream_decoder_get_resolved_state_string(decoder));\r
                return false;\r
        }\r
        /* check results */\r
-       if (file_info->abort_flag) return false;                /* metadata callback already popped up the error dialog */\r
+       if (stream_data->abort_flag) return false;                /* metadata callback already popped up the error dialog */\r
        /* init replaygain */\r
-       file_info->output_bits_per_sample = file_info->has_replaygain && cfg.replaygain.enable ?\r
+       stream_data->output_bits_per_sample = stream_data->has_replaygain && cfg.replaygain.enable ?\r
                cfg.resolution.replaygain.bps_out :\r
-               cfg.resolution.normal.dither_24_to_16 ? min(file_info->bits_per_sample, 16) : file_info->bits_per_sample;\r
+               cfg.resolution.normal.dither_24_to_16 ? min(stream_data->bits_per_sample, 16) : stream_data->bits_per_sample;\r
 \r
-       if (file_info->has_replaygain && cfg.replaygain.enable && cfg.resolution.replaygain.dither)\r
-               FLAC__replaygain_synthesis__init_dither_context(&file_info->dither_context, file_info->bits_per_sample, cfg.resolution.replaygain.noise_shaping);\r
+       if (stream_data->has_replaygain && cfg.replaygain.enable && cfg.resolution.replaygain.dither)\r
+               FLAC__replaygain_synthesis__init_dither_context(&stream_data->dither_context, stream_data->bits_per_sample, cfg.resolution.replaygain.noise_shaping);\r
        /* more inits */\r
-       file_info->eof = false;\r
-       file_info->seek_to = -1;\r
-       file_info->is_playing = true;\r
-       file_info->average_bps = (unsigned)(filesize / (125.*(double)(FLAC__int64)file_info->total_samples/(double)file_info->sample_rate));\r
+       stream_data->eof = false;\r
+       stream_data->seek_to = -1;\r
+       stream_data->is_playing = true;\r
+       stream_data->average_bps = (unsigned)(filesize / (125.*(double)(FLAC__int64)stream_data->total_samples/(double)stream_data->sample_rate));\r
        \r
        bh_index_last_w = 0;\r
        bh_index_last_o = BITRATE_HIST_SIZE;\r
@@ -165,18 +162,18 @@ FLAC__bool FLAC_plugin__decoder_init(FLAC__FileDecoder *decoder, const char *fil
        return true;\r
 }\r
 \r
-void FLAC_plugin__decoder_finish(FLAC__FileDecoder *decoder)\r
+void FLAC_plugin__decoder_finish(FLAC__StreamDecoder *decoder)\r
 {\r
-       if (decoder && FLAC__file_decoder_get_state(decoder)!=FLAC__FILE_DECODER_UNINITIALIZED)\r
-               FLAC__file_decoder_finish(decoder);\r
+       if (decoder && FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_UNINITIALIZED)\r
+               FLAC__stream_decoder_finish(decoder);\r
 }\r
 \r
-void FLAC_plugin__decoder_delete(FLAC__FileDecoder *decoder)\r
+void FLAC_plugin__decoder_delete(FLAC__StreamDecoder *decoder)\r
 {\r
        if (decoder)\r
        {\r
                FLAC_plugin__decoder_finish(decoder);\r
-               FLAC__file_decoder_delete(decoder);\r
+               FLAC__stream_decoder_delete(decoder);\r
        }\r
 }\r
 \r
@@ -184,68 +181,75 @@ void FLAC_plugin__decoder_delete(FLAC__FileDecoder *decoder)
  *  decode\r
  */\r
 \r
-int FLAC_plugin__seek(FLAC__FileDecoder *decoder, file_info_struct *file_info)\r
+int FLAC_plugin__seek(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data)\r
 {\r
        int pos;\r
-       const FLAC__uint64 target_sample = file_info->total_samples * file_info->seek_to / file_info->length_in_msec;\r
+       FLAC__uint64 target_sample = stream_data->total_samples * stream_data->seek_to / stream_data->length_in_msec;\r
 \r
-       if (!FLAC__file_decoder_seek_absolute(decoder, target_sample))\r
-               return -1;\r
+       if (stream_data->total_samples > 0 && target_sample >= stream_data->total_samples && target_sample > 0)\r
+               target_sample = stream_data->total_samples - 1;\r
 \r
-       file_info->seek_to = -1;\r
-       file_info->eof = false;\r
+       /* even if the seek fails we have to reset these so that we don't repeat the seek */\r
+       stream_data->seek_to = -1;\r
+       stream_data->eof = false;\r
        wide_samples_in_reservoir_ = 0;\r
-       pos = (int)(target_sample*1000 / file_info->sample_rate);\r
+       pos = (int)(target_sample*1000 / stream_data->sample_rate);\r
+\r
+       if (!FLAC__stream_decoder_seek_absolute(decoder, target_sample)) {\r
+               if(FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_SEEK_ERROR)\r
+                       FLAC__stream_decoder_flush(decoder);\r
+               pos = -1;\r
+       }\r
 \r
        bh_index_last_o = bh_index_last_w = (pos/BITRATE_HIST_SEGMENT_MSEC) % BITRATE_HIST_SIZE;\r
-       if (!FLAC__file_decoder_get_decode_position(decoder, &decode_position))\r
+       if (!FLAC__stream_decoder_get_decode_position(decoder, &decode_position))\r
                decode_position = 0;\r
 \r
        return pos;\r
 }\r
 \r
-unsigned FLAC_plugin__decode(FLAC__FileDecoder *decoder, file_info_struct *file_info, char *sample_buffer)\r
+unsigned FLAC_plugin__decode(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data, char *sample_buffer)\r
 {\r
        /* fill reservoir */\r
        while (wide_samples_in_reservoir_ < SAMPLES_PER_WRITE)\r
        {\r
-               if (FLAC__file_decoder_get_state(decoder) == FLAC__FILE_DECODER_END_OF_FILE)\r
+               if (FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)\r
                {\r
-                       file_info->eof = true;\r
+                       stream_data->eof = true;\r
                        break;\r
                }\r
-               else if (!FLAC__file_decoder_process_single(decoder))\r
+               else if (!FLAC__stream_decoder_process_single(decoder))\r
                {\r
-                       FLAC_plugin__show_error("Error while processing frame (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);\r
-                       file_info->eof = true;\r
+                       FLAC_plugin__show_error("Error while processing frame (%s).", FLAC__stream_decoder_get_resolved_state_string(decoder));\r
+                       stream_data->eof = true;\r
                        break;\r
                }\r
-               if (!FLAC__file_decoder_get_decode_position(decoder, &decode_position))\r
+               if (!FLAC__stream_decoder_get_decode_position(decoder, &decode_position))\r
                        decode_position = 0;\r
        }\r
        /* output samples */\r
        if (wide_samples_in_reservoir_ > 0)\r
        {\r
                const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE);\r
-               const unsigned channels = file_info->channels;\r
+               const unsigned channels = stream_data->channels;\r
                unsigned i;\r
                int bytes;\r
 \r
-               if (cfg.replaygain.enable && file_info->has_replaygain)\r
+               if (cfg.replaygain.enable && stream_data->has_replaygain)\r
                {\r
                        bytes = FLAC__replaygain_synthesis__apply_gain(\r
                                sample_buffer,\r
                                true, /* little_endian_data_out */\r
-                               file_info->output_bits_per_sample == 8, /* unsigned_data_out */\r
+                               stream_data->output_bits_per_sample == 8, /* unsigned_data_out */\r
                                reservoir__,\r
                                n,\r
                                channels,\r
-                               file_info->bits_per_sample,\r
-                               file_info->output_bits_per_sample,\r
-                               file_info->replay_scale,\r
+                               stream_data->bits_per_sample,\r
+                               stream_data->output_bits_per_sample,\r
+                               stream_data->replay_scale,\r
                                cfg.replaygain.hard_limit,\r
                                cfg.resolution.replaygain.dither,\r
-                               &file_info->dither_context\r
+                               &stream_data->dither_context\r
                        );\r
                }\r
                else\r
@@ -255,8 +259,8 @@ unsigned FLAC_plugin__decode(FLAC__FileDecoder *decoder, file_info_struct *file_
                                reservoir__,\r
                                n,\r
                                channels,\r
-                               file_info->bits_per_sample,\r
-                               file_info->output_bits_per_sample\r
+                               stream_data->bits_per_sample,\r
+                               stream_data->output_bits_per_sample\r
                        );\r
                }\r
 \r
@@ -268,12 +272,12 @@ unsigned FLAC_plugin__decode(FLAC__FileDecoder *decoder, file_info_struct *file_
        }\r
        else\r
        {\r
-               file_info->eof = true;\r
+               stream_data->eof = true;\r
                return 0;\r
        }\r
 }\r
 \r
-int FLAC_plugin__get_rate(unsigned written_time, unsigned output_time, file_info_struct *file_info)\r
+int FLAC_plugin__get_rate(unsigned written_time, unsigned output_time, stream_data_struct *stream_data)\r
 {\r
        static int bitrate_history_[BITRATE_HIST_SIZE];\r
        unsigned bh_index_w = (written_time/BITRATE_HIST_SEGMENT_MSEC) % BITRATE_HIST_SIZE;\r
@@ -285,7 +289,7 @@ int FLAC_plugin__get_rate(unsigned written_time, unsigned output_time, file_info
                bitrate_history_[(bh_index_w + BITRATE_HIST_SIZE-1)%BITRATE_HIST_SIZE] =\r
                        decode_position>decode_position_last && written_time > written_time_last ?\r
                        (unsigned)(8000*(decode_position - decode_position_last)/(written_time - written_time_last)) :\r
-                       file_info->average_bps;\r
+                       stream_data->average_bps;\r
 \r
                bh_index_last_w = bh_index_w;\r
                written_time_last = written_time;\r
index 4120791..30f8093 100644 (file)
@@ -48,7 +48,7 @@ typedef struct {
        FLAC__bool has_replaygain;\r
        double replay_scale;\r
        DitherContext dither_context;\r
-} file_info_struct;\r
+} stream_data_struct;\r
 \r
 \r
 typedef struct {\r
@@ -77,13 +77,13 @@ typedef struct {
  *  protopytes\r
  */\r
 \r
-FLAC__bool FLAC_plugin__decoder_init(FLAC__FileDecoder *decoder, const char *filename, FLAC__int64 filesize, file_info_struct *file_info, output_config_t *config);\r
-void FLAC_plugin__decoder_finish(FLAC__FileDecoder *decoder);\r
-void FLAC_plugin__decoder_delete(FLAC__FileDecoder *decoder);\r
+FLAC__bool FLAC_plugin__decoder_init(FLAC__StreamDecoder *decoder, const char *filename, FLAC__int64 filesize, stream_data_struct *stream_data, output_config_t *config);\r
+void FLAC_plugin__decoder_finish(FLAC__StreamDecoder *decoder);\r
+void FLAC_plugin__decoder_delete(FLAC__StreamDecoder *decoder);\r
 \r
-int FLAC_plugin__seek(FLAC__FileDecoder *decoder, file_info_struct *file_info);\r
-unsigned FLAC_plugin__decode(FLAC__FileDecoder *decoder, file_info_struct *file_info, char *sample_buffer);\r
-int FLAC_plugin__get_rate(unsigned written_time, unsigned output_time, file_info_struct *file_info);\r
+int FLAC_plugin__seek(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data);\r
+unsigned FLAC_plugin__decode(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data, char *sample_buffer);\r
+int FLAC_plugin__get_rate(unsigned written_time, unsigned output_time, stream_data_struct *stream_data);\r
 \r
 /*\r
  *  these should be defined in plug-in\r
index fadede1..a99c2c2 100644 (file)
@@ -709,7 +709,7 @@ static void *http_buffer_loop(void *arg)
        return NULL; /* avoid compiler warning */
 }
 
-int flac_http_open(gchar * _url, guint64 _offset)
+int flac_http_open(const gchar * _url, guint64 _offset)
 {
        gchar *url;
 
index 4ba40ce..0025430 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef FLAC__PLUGIN_XMMS__HTTP_H
 #define FLAC__PLUGIN_XMMS__HTTP_H
 
-extern int flac_http_open(gchar * url, guint64 offset);
+extern int flac_http_open(const gchar * url, guint64 offset);
 extern void flac_http_close(void);
 extern int flac_http_read(gpointer data, gint length);
 
index d6f409f..4e5b9a1 100644 (file)
@@ -58,6 +58,7 @@ extern void FLAC_XMMS__file_info_box(char *filename);
 typedef struct {
        FLAC__bool abort_flag;
        FLAC__bool is_playing;
+       FLAC__bool is_http_source;
        FLAC__bool eof;
        FLAC__bool play_thread_open; /* if true, is_playing must also be true */
        FLAC__uint64 total_samples;
@@ -72,36 +73,7 @@ typedef struct {
        FLAC__bool has_replaygain;
        double replay_scale;
        DitherContext dither_context;
-} file_info_struct;
-
-typedef FLAC__StreamDecoderWriteStatus (*WriteCallback) (const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-typedef void (*MetadataCallback) (const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-typedef void (*ErrorCallback) (const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-
-typedef struct {
-       FLAC__bool seekable;
-       void* (*new_decoder) (void);
-       FLAC__bool (*set_md5_checking) (void *decoder, FLAC__bool value);
-       FLAC__bool (*set_source) (void *decoder, const char* source);
-       FLAC__bool (*set_metadata_ignore_all) (void *decoder);
-       FLAC__bool (*set_metadata_respond) (void *decoder, FLAC__MetadataType type);
-       FLAC__bool (*set_write_callback) (void *decoder, WriteCallback value);
-       FLAC__bool (*set_metadata_callback) (void *decoder, MetadataCallback value);
-       FLAC__bool (*set_error_callback) (void *decoder, ErrorCallback value);
-       FLAC__bool (*set_client_data) (void *decoder, void *value);
-       FLAC__bool (*decoder_init) (void *decoder);
-       void (*safe_decoder_finish) (void *decoder);
-       void (*safe_decoder_delete) (void *decoder);
-       FLAC__bool (*process_until_end_of_metadata) (void *decoder);
-       FLAC__bool (*process_single) (void *decoder);
-       FLAC__bool (*is_eof) (void *decoder);
-} decoder_funcs_t;
-
-#define NUM_DECODER_TYPES 2
-typedef enum {
-       DECODER_FILE,
-       DECODER_HTTP
-} decoder_t;
+} stream_data_struct;
 
 static void FLAC_XMMS__init();
 static int  FLAC_XMMS__is_our_file(char *filename);
@@ -115,15 +87,14 @@ static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length);
 
 static void *play_loop_(void *arg);
 
-static FLAC__bool safe_decoder_init_(const char *filename, void **decoderp, decoder_funcs_t const ** fnsp);
-static void file_decoder_safe_decoder_finish_(void *decoder);
-static void file_decoder_safe_decoder_delete_(void *decoder);
-static FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
-static void metadata_callback_(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
-static void error_callback_(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static FLAC__bool safe_decoder_init_(const char *filename, FLAC__StreamDecoder *decoder);
+static void safe_decoder_finish_(FLAC__StreamDecoder *decoder);
+static void safe_decoder_delete_(FLAC__StreamDecoder *decoder);
 
-static void init_decoder_func_tables();
-static decoder_t source_to_decoder_type (const char *source);
+static FLAC__StreamDecoderReadStatus http_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
 
 InputPlugin flac_ip =
 {
@@ -158,8 +129,8 @@ InputPlugin flac_ip =
 static FLAC__byte sample_buffer_[SAMPLE_BUFFER_SIZE];
 static unsigned sample_buffer_first_, sample_buffer_last_;
 
-static void *decoder_ = 0;
-static file_info_struct file_info_;
+static FLAC__StreamDecoder *decoder_ = 0;
+static stream_data_struct stream_data_;
 static pthread_t decode_thread_;
 static FLAC__bool audio_error_ = false;
 static FLAC__bool is_big_endian_host_;
@@ -169,11 +140,6 @@ static FLAC__bool is_big_endian_host_;
 #define BITRATE_HIST_SIZE 50
 static unsigned bitrate_history_[BITRATE_HIST_SIZE];
 
-/* A table of sets of decoder functions, indexed by decoder_t */
-static const decoder_funcs_t* DECODER_FUNCS[NUM_DECODER_TYPES];
-
-static decoder_funcs_t const * decoder_func_table_;
-
 
 InputPlugin *get_iplugin_info()
 {
@@ -183,8 +149,8 @@ InputPlugin *get_iplugin_info()
 
 void set_track_info(const char* title, int length_in_msec)
 {
-       if (file_info_.is_playing) {
-               flac_ip.set_info((char*) title, length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels);
+       if (stream_data_.is_playing) {
+               flac_ip.set_info((char*) title, length_in_msec, stream_data_.sample_rate * stream_data_.channels * stream_data_.bits_per_sample, stream_data_.sample_rate, stream_data_.channels);
        }
 }
 
@@ -206,6 +172,11 @@ static gchar* homedir()
        return result;
 }
 
+static FLAC__bool is_http_source(const char *source)
+{
+       return 0 == strncasecmp(source, "http://", 7);
+}
+
 void FLAC_XMMS__init()
 {
        ConfigFile *cfg;
@@ -282,9 +253,7 @@ void FLAC_XMMS__init()
        xmms_cfg_read_boolean(cfg, "flac", "stream.cast_title_streaming", &flac_cfg.stream.cast_title_streaming);
        xmms_cfg_read_boolean(cfg, "flac", "stream.use_udp_channel", &flac_cfg.stream.use_udp_channel);
 
-       init_decoder_func_tables();
-       decoder_func_table_ = DECODER_FUNCS [DECODER_FILE];
-       decoder_ = decoder_func_table_ -> new_decoder();
+       decoder_ = FLAC__stream_decoder_new();
 
        xmms_cfg_free(cfg);
 }
@@ -306,13 +275,14 @@ void FLAC_XMMS__play_file(char *filename)
 
        sample_buffer_first_ = sample_buffer_last_ = 0;
        audio_error_ = false;
-       file_info_.abort_flag = false;
-       file_info_.is_playing = false;
-       file_info_.eof = false;
-       file_info_.play_thread_open = false;
-       file_info_.has_replaygain = false;
-
-       if (source_to_decoder_type (filename) == DECODER_FILE) {
+       stream_data_.abort_flag = false;
+       stream_data_.is_playing = false;
+       stream_data_.is_http_source = is_http_source(filename);
+       stream_data_.eof = false;
+       stream_data_.play_thread_open = false;
+       stream_data_.has_replaygain = false;
+
+       if(!is_http_source(filename)) {
                if(0 == (f = fopen(filename, "r")))
                        return;
                fclose(f);
@@ -321,68 +291,68 @@ void FLAC_XMMS__play_file(char *filename)
        if(decoder_ == 0)
                return;
 
-       if(!safe_decoder_init_(filename, &decoder_, &decoder_func_table_))
+       if(!safe_decoder_init_(filename, decoder_))
                return;
 
-       if(file_info_.has_replaygain && flac_cfg.output.replaygain.enable) {
+       if(stream_data_.has_replaygain && flac_cfg.output.replaygain.enable) {
                if(flac_cfg.output.resolution.replaygain.bps_out == 8) {
-                       file_info_.sample_format = FMT_U8;
-                       file_info_.sample_format_bytes_per_sample = 1;
+                       stream_data_.sample_format = FMT_U8;
+                       stream_data_.sample_format_bytes_per_sample = 1;
                }
                else if(flac_cfg.output.resolution.replaygain.bps_out == 16) {
-                       file_info_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE;
-                       file_info_.sample_format_bytes_per_sample = 2;
+                       stream_data_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE;
+                       stream_data_.sample_format_bytes_per_sample = 2;
                }
                else {
                        /*@@@ need some error here like wa2: MessageBox(mod_.hMainWindow, "ERROR: plugin can only handle 8/16-bit samples\n", "ERROR: plugin can only handle 8/16-bit samples", 0); */
                        fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", flac_cfg.output.resolution.replaygain.bps_out);
-                       decoder_func_table_ -> safe_decoder_finish(decoder_);
+                       safe_decoder_finish_(decoder_);
                        return;
                }
        }
        else {
-               if(file_info_.bits_per_sample == 8) {
-                       file_info_.sample_format = FMT_U8;
-                       file_info_.sample_format_bytes_per_sample = 1;
+               if(stream_data_.bits_per_sample == 8) {
+                       stream_data_.sample_format = FMT_U8;
+                       stream_data_.sample_format_bytes_per_sample = 1;
                }
-               else if(file_info_.bits_per_sample == 16 || (file_info_.bits_per_sample == 24 && flac_cfg.output.resolution.normal.dither_24_to_16)) {
-                       file_info_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE;
-                       file_info_.sample_format_bytes_per_sample = 2;
+               else if(stream_data_.bits_per_sample == 16 || (stream_data_.bits_per_sample == 24 && flac_cfg.output.resolution.normal.dither_24_to_16)) {
+                       stream_data_.sample_format = (is_big_endian_host_) ? FMT_S16_BE : FMT_S16_LE;
+                       stream_data_.sample_format_bytes_per_sample = 2;
                }
                else {
                        /*@@@ need some error here like wa2: MessageBox(mod_.hMainWindow, "ERROR: plugin can only handle 8/16-bit samples\n", "ERROR: plugin can only handle 8/16-bit samples", 0); */
-                       fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", file_info_.bits_per_sample);
-                       decoder_func_table_ -> safe_decoder_finish(decoder_);
+                       fprintf(stderr, "libxmms-flac: can't handle %d bit output\n", stream_data_.bits_per_sample);
+                       safe_decoder_finish_(decoder_);
                        return;
                }
        }
-       FLAC__replaygain_synthesis__init_dither_context(&file_info_.dither_context, file_info_.sample_format_bytes_per_sample * 8, flac_cfg.output.resolution.replaygain.noise_shaping);
-       file_info_.is_playing = true;
+       FLAC__replaygain_synthesis__init_dither_context(&stream_data_.dither_context, stream_data_.sample_format_bytes_per_sample * 8, flac_cfg.output.resolution.replaygain.noise_shaping);
+       stream_data_.is_playing = true;
 
-       if(flac_ip.output->open_audio(file_info_.sample_format, file_info_.sample_rate, file_info_.channels) == 0) {
+       if(flac_ip.output->open_audio(stream_data_.sample_format, stream_data_.sample_rate, stream_data_.channels) == 0) {
                audio_error_ = true;
-               decoder_func_table_ -> safe_decoder_finish(decoder_);
+               safe_decoder_finish_(decoder_);
                return;
        }
 
-       file_info_.title = flac_format_song_title(filename);
-       flac_ip.set_info(file_info_.title, file_info_.length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels);
+       stream_data_.title = flac_format_song_title(filename);
+       flac_ip.set_info(stream_data_.title, stream_data_.length_in_msec, stream_data_.sample_rate * stream_data_.channels * stream_data_.bits_per_sample, stream_data_.sample_rate, stream_data_.channels);
 
-       file_info_.seek_to_in_sec = -1;
-       file_info_.play_thread_open = true;
+       stream_data_.seek_to_in_sec = -1;
+       stream_data_.play_thread_open = true;
        pthread_create(&decode_thread_, NULL, play_loop_, NULL);
 }
 
 void FLAC_XMMS__stop()
 {
-       if(file_info_.is_playing) {
-               file_info_.is_playing = false;
-               if(file_info_.play_thread_open) {
-                       file_info_.play_thread_open = false;
+       if(stream_data_.is_playing) {
+               stream_data_.is_playing = false;
+               if(stream_data_.play_thread_open) {
+                       stream_data_.play_thread_open = false;
                        pthread_join(decode_thread_, NULL);
                }
                flac_ip.output->close_audio();
-               decoder_func_table_ -> safe_decoder_finish (decoder_);
+               safe_decoder_finish_(decoder_);
        }
 }
 
@@ -393,11 +363,11 @@ void FLAC_XMMS__pause(short p)
 
 void FLAC_XMMS__seek(int time)
 {
-       if (decoder_func_table_->seekable) {
-               file_info_.seek_to_in_sec = time;
-               file_info_.eof = false;
+       if(!stream_data_.is_http_source) {
+               stream_data_.seek_to_in_sec = time;
+               stream_data_.eof = false;
 
-               while(file_info_.seek_to_in_sec != -1)
+               while(stream_data_.seek_to_in_sec != -1)
                        xmms_usleep(10000);
        }
 }
@@ -406,7 +376,7 @@ int FLAC_XMMS__get_time()
 {
        if(audio_error_)
                return -2;
-       if(!file_info_.is_playing || (file_info_.eof && !flac_ip.output->buffer_playing()))
+       if(!stream_data_.is_playing || (stream_data_.eof && !flac_ip.output->buffer_playing()))
                return -1;
        else
                return flac_ip.output->output_time();
@@ -414,7 +384,7 @@ int FLAC_XMMS__get_time()
 
 void FLAC_XMMS__cleanup()
 {
-       decoder_func_table_ -> safe_decoder_delete(decoder_);
+       safe_decoder_delete_(decoder_);
        decoder_ = 0;
 }
 
@@ -428,7 +398,7 @@ void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec)
        if(!FLAC__metadata_get_streaminfo(filename, &streaminfo)) {
                /* @@@ how to report the error? */
                if(title) {
-                       if (source_to_decoder_type (filename) == DECODER_FILE) {
+                       if (!is_http_source(filename)) {
                                static const char *errtitle = "Invalid FLAC File: ";
                                *title = g_malloc(strlen(errtitle) + 1 + strlen(filename) + 1 + 1);
                                sprintf(*title, "%s\"%s\"", errtitle, filename);
@@ -463,39 +433,39 @@ void *play_loop_(void *arg)
 
        (void)arg;
 
-       while(file_info_.is_playing) {
-               if(!file_info_.eof) {
+       while(stream_data_.is_playing) {
+               if(!stream_data_.eof) {
                        while(sample_buffer_last_ - sample_buffer_first_ < SAMPLES_PER_WRITE) {
                                unsigned s;
 
                                s = sample_buffer_last_ - sample_buffer_first_;
-                               if(decoder_func_table_ -> is_eof(decoder_)) {
-                                       file_info_.eof = true;
+                               if(FLAC__stream_decoder_get_state(decoder_) == FLAC__STREAM_DECODER_END_OF_STREAM) {
+                                       stream_data_.eof = true;
                                        break;
                                }
-                               else if (!decoder_func_table_ -> process_single(decoder_)) {
+                               else if(!FLAC__stream_decoder_process_single(decoder_)) {
                                        /*@@@ this should probably be a dialog */
                                        fprintf(stderr, "libxmms-flac: READ ERROR processing frame\n");
-                                       file_info_.eof = true;
+                                       stream_data_.eof = true;
                                        break;
                                }
                                blocksize = sample_buffer_last_ - sample_buffer_first_ - s;
                                decode_position_frame_last = decode_position_frame;
-                               if(!decoder_func_table_->seekable || !FLAC__file_decoder_get_decode_position(decoder_, &decode_position_frame))
+                               if(stream_data_.is_http_source || !FLAC__stream_decoder_get_decode_position(decoder_, &decode_position_frame))
                                        decode_position_frame = 0;
                        }
                        if(sample_buffer_last_ - sample_buffer_first_ > 0) {
                                const unsigned n = min(sample_buffer_last_ - sample_buffer_first_, SAMPLES_PER_WRITE);
-                               int bytes = n * file_info_.channels * file_info_.sample_format_bytes_per_sample;
-                               FLAC__byte *sample_buffer_start = sample_buffer_ + sample_buffer_first_ * file_info_.channels * file_info_.sample_format_bytes_per_sample;
+                               int bytes = n * stream_data_.channels * stream_data_.sample_format_bytes_per_sample;
+                               FLAC__byte *sample_buffer_start = sample_buffer_ + sample_buffer_first_ * stream_data_.channels * stream_data_.sample_format_bytes_per_sample;
                                unsigned written_time, bh_index_w;
                                FLAC__uint64 decode_position;
 
                                sample_buffer_first_ += n;
-                               flac_ip.add_vis_pcm(flac_ip.output->written_time(), file_info_.sample_format, file_info_.channels, bytes, sample_buffer_start);
-                               while(flac_ip.output->buffer_free() < (int)bytes && file_info_.is_playing && file_info_.seek_to_in_sec == -1)
+                               flac_ip.add_vis_pcm(flac_ip.output->written_time(), stream_data_.sample_format, stream_data_.channels, bytes, sample_buffer_start);
+                               while(flac_ip.output->buffer_free() < (int)bytes && stream_data_.is_playing && stream_data_.seek_to_in_sec == -1)
                                        xmms_usleep(10000);
-                               if(file_info_.is_playing && file_info_.seek_to_in_sec == -1)
+                               if(stream_data_.is_playing && stream_data_.seek_to_in_sec == -1)
                                        flac_ip.output->write_audio(sample_buffer_start, bytes);
 
                                /* compute current bitrate */
@@ -508,262 +478,145 @@ void *play_loop_(void *arg)
                                        bitrate_history_[(bh_index_w + BITRATE_HIST_SIZE - 1) % BITRATE_HIST_SIZE] =
                                                decode_position > decode_position_last && written_time > written_time_last ?
                                                        8000 * (decode_position - decode_position_last) / (written_time - written_time_last) :
-                                                       file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample;
+                                                       stream_data_.sample_rate * stream_data_.channels * stream_data_.bits_per_sample;
                                        decode_position_last = decode_position;
                                        written_time_last = written_time;
                                }
                        }
                        else {
-                               file_info_.eof = true;
+                               stream_data_.eof = true;
                                xmms_usleep(10000);
                        }
                }
                else
                        xmms_usleep(10000);
-               if(decoder_func_table_->seekable && file_info_.seek_to_in_sec != -1) {
-                       const double distance = (double)file_info_.seek_to_in_sec * 1000.0 / (double)file_info_.length_in_msec;
-                       FLAC__uint64 target_sample = (FLAC__uint64)(distance * (double)file_info_.total_samples);
-                       if(FLAC__file_decoder_seek_absolute(decoder_, target_sample)) {
-                               flac_ip.output->flush(file_info_.seek_to_in_sec * 1000);
+               if(!stream_data_.is_http_source && stream_data_.seek_to_in_sec != -1) {
+                       const double distance = (double)stream_data_.seek_to_in_sec * 1000.0 / (double)stream_data_.length_in_msec;
+                       FLAC__uint64 target_sample = (FLAC__uint64)(distance * (double)stream_data_.total_samples);
+                       if(stream_data_.total_samples > 0 && target_sample >= stream_data_.total_samples)
+                               target_sample = stream_data_.total_samples - 1;
+                       if(FLAC__stream_decoder_seek_absolute(decoder_, target_sample)) {
+                               flac_ip.output->flush(stream_data_.seek_to_in_sec * 1000);
                                bh_index_last_w = bh_index_last_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE;
-                               if(!FLAC__file_decoder_get_decode_position(decoder_, &decode_position_frame))
+                               if(!FLAC__stream_decoder_get_decode_position(decoder_, &decode_position_frame))
                                        decode_position_frame = 0;
-                               file_info_.seek_to_in_sec = -1;
-                               file_info_.eof = false;
+                               stream_data_.eof = false;
                                sample_buffer_first_ = sample_buffer_last_ = 0;
                        }
+                       else if(FLAC__stream_decoder_get_state(decoder_) == FLAC__STREAM_DECODER_SEEK_ERROR) {
+                               /*@@@ this should probably be a dialog */
+                               fprintf(stderr, "libxmms-flac: SEEK ERROR\n");
+                               FLAC__stream_decoder_flush(decoder_);
+                               stream_data_.eof = false;
+                               sample_buffer_first_ = sample_buffer_last_ = 0;
+                       }
+                       stream_data_.seek_to_in_sec = -1;
                }
                else {
                        /* display the right bitrate from history */
                        unsigned bh_index_o = flac_ip.output->output_time() / BITRATE_HIST_SEGMENT_MSEC % BITRATE_HIST_SIZE;
                        if(bh_index_o != bh_index_last_o && bh_index_o != bh_index_last_w && bh_index_o != (bh_index_last_w + 1) % BITRATE_HIST_SIZE) {
                                bh_index_last_o = bh_index_o;
-                               flac_ip.set_info(file_info_.title, file_info_.length_in_msec, bitrate_history_[bh_index_o], file_info_.sample_rate, file_info_.channels);
+                               flac_ip.set_info(stream_data_.title, stream_data_.length_in_msec, bitrate_history_[bh_index_o], stream_data_.sample_rate, stream_data_.channels);
                        }
                }
        }
 
-       decoder_func_table_ -> safe_decoder_finish(decoder_);
+       safe_decoder_finish_(decoder_);
 
        /* are these two calls necessary? */
        flac_ip.output->buffer_free();
        flac_ip.output->buffer_free();
 
-       g_free(file_info_.title);
+       g_free(stream_data_.title);
 
        pthread_exit(NULL);
        return 0; /* to silence the compiler warning about not returning a value */
 }
 
-/*********** File decoder functions */
-
-static FLAC__bool file_decoder_init (void *decoder)
+FLAC__bool safe_decoder_init_(const char *filename, FLAC__StreamDecoder *decoder)
 {
-       return FLAC__file_decoder_init( (FLAC__FileDecoder*) decoder) == FLAC__FILE_DECODER_OK;
-}
+       if(decoder == 0)
+               return false;
 
-static void file_decoder_safe_decoder_finish_(void *decoder)
-{
-       if(decoder && FLAC__file_decoder_get_state((FLAC__FileDecoder *) decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
-               FLAC__file_decoder_finish((FLAC__FileDecoder *) decoder);
-}
+       safe_decoder_finish_(decoder);
 
-static void file_decoder_safe_decoder_delete_(void *decoder)
-{
-       if(decoder) {
-               file_decoder_safe_decoder_finish_(decoder);
-               FLAC__file_decoder_delete( (FLAC__FileDecoder *) decoder);
+       FLAC__stream_decoder_set_md5_checking(decoder, false);
+       FLAC__stream_decoder_set_metadata_ignore_all(decoder);
+       FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
+       FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
+       if(stream_data_.is_http_source) {
+               flac_http_open(filename, 0);
+               if(FLAC__stream_decoder_init_stream(decoder, http_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, write_callback_, metadata_callback_, error_callback_, /*client_data=*/&stream_data_) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                       return false;
+       }
+       else {
+               if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, /*client_data=*/&stream_data_) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                       return false;
        }
-}
-
-static FLAC__bool file_decoder_is_eof(void *decoder)
-{
-       return FLAC__file_decoder_get_state((FLAC__FileDecoder *) decoder) == FLAC__FILE_DECODER_END_OF_FILE;
-}
-
-static const decoder_funcs_t FILE_DECODER_FUNCTIONS = {
-       true,
-       (void* (*) (void)) FLAC__file_decoder_new,
-       (FLAC__bool (*) (void *, FLAC__bool)) FLAC__file_decoder_set_md5_checking,
-       (FLAC__bool (*) (void *, const char*)) FLAC__file_decoder_set_filename,
-       (FLAC__bool (*) (void *)) FLAC__file_decoder_set_metadata_ignore_all,
-       (FLAC__bool (*) (void *, FLAC__MetadataType)) FLAC__file_decoder_set_metadata_respond,
-       (FLAC__bool (*) (void *, WriteCallback)) FLAC__file_decoder_set_write_callback,
-       (FLAC__bool (*) (void *, MetadataCallback)) FLAC__file_decoder_set_metadata_callback,
-       (FLAC__bool (*) (void *, ErrorCallback)) FLAC__file_decoder_set_error_callback,
-       (FLAC__bool (*) (void *, void *)) FLAC__file_decoder_set_client_data,
-       (FLAC__bool (*) (void *)) file_decoder_init,
-       (void (*) (void *)) file_decoder_safe_decoder_finish_,
-       (void (*) (void *)) file_decoder_safe_decoder_delete_,
-       (FLAC__bool (*) (void *)) FLAC__file_decoder_process_until_end_of_metadata,
-       (FLAC__bool (*) (void *)) FLAC__file_decoder_process_single,
-       file_decoder_is_eof
-};
-
-/*********** HTTP decoder functions */
-
-static gchar *url_;
 
-static FLAC__bool http_decoder_set_md5_checking (void *decoder, FLAC__bool value)
-{
-       (void) value;
-       // operation unsupported
-       return FLAC__stream_decoder_get_state ((const FLAC__StreamDecoder *) decoder) == FLAC__STREAM_DECODER_UNINITIALIZED;
-}
+       if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder))
+               return false;
 
-static FLAC__bool http_decoder_set_url (void *decoder, const char* url)
-{
-       (void) decoder;
-       url_ = g_strdup (url);
        return true;
 }
 
-static FLAC__StreamDecoderReadStatus http_decoder_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-{
-       (void) decoder;
-       (void) client_data;
-       *bytes = flac_http_read (buffer, *bytes);
-       return *bytes ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-}
-
-static FLAC__bool http_decoder_init (void *decoder)
-{
-       flac_http_open (url_, 0);
-       g_free (url_);
-       FLAC__stream_decoder_set_read_callback (decoder, http_decoder_read_callback);
-       return FLAC__stream_decoder_init( (FLAC__StreamDecoder*) decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
-}
-
-static void http_decoder_safe_decoder_finish_(void *decoder)
+void safe_decoder_finish_(FLAC__StreamDecoder *decoder)
 {
-       if(decoder && FLAC__stream_decoder_get_state((FLAC__StreamDecoder *) decoder) != FLAC__STREAM_DECODER_UNINITIALIZED) {
-               FLAC__stream_decoder_finish((FLAC__StreamDecoder *) decoder);
+       if(decoder && FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_UNINITIALIZED)
+               FLAC__stream_decoder_finish(decoder);
+       if(stream_data_.is_http_source)
                flac_http_close();
-       }
 }
 
-static void http_decoder_safe_decoder_delete_(void *decoder)
+void safe_decoder_delete_(FLAC__StreamDecoder *decoder)
 {
        if(decoder) {
-               http_decoder_safe_decoder_finish_(decoder);
-               FLAC__stream_decoder_delete( (FLAC__StreamDecoder *) decoder);
-       }
-}
-
-static FLAC__bool http_decoder_is_eof(void *decoder)
-{
-       return FLAC__stream_decoder_get_state((FLAC__StreamDecoder *) decoder) == FLAC__STREAM_DECODER_END_OF_STREAM;
-}
-
-static const decoder_funcs_t HTTP_DECODER_FUNCTIONS = {
-       false,
-       (void* (*) (void)) FLAC__stream_decoder_new,
-       http_decoder_set_md5_checking,
-       (FLAC__bool (*) (void *, const char*)) http_decoder_set_url,
-       (FLAC__bool (*) (void *)) FLAC__stream_decoder_set_metadata_ignore_all,
-       (FLAC__bool (*) (void *, FLAC__MetadataType)) FLAC__stream_decoder_set_metadata_respond,
-       (FLAC__bool (*) (void *, WriteCallback)) FLAC__stream_decoder_set_write_callback,
-       (FLAC__bool (*) (void *, MetadataCallback)) FLAC__stream_decoder_set_metadata_callback,
-       (FLAC__bool (*) (void *, ErrorCallback)) FLAC__stream_decoder_set_error_callback,
-       (FLAC__bool (*) (void *, void *)) FLAC__stream_decoder_set_client_data,
-       (FLAC__bool (*) (void *)) http_decoder_init,
-       (void (*) (void *)) http_decoder_safe_decoder_finish_,
-       (void (*) (void *)) http_decoder_safe_decoder_delete_,
-       (FLAC__bool (*) (void *)) FLAC__stream_decoder_process_until_end_of_metadata,
-       (FLAC__bool (*) (void *)) FLAC__stream_decoder_process_single,
-       http_decoder_is_eof
-};
-
-static decoder_funcs_t const *decoder_func_table_;
-
-static void init_decoder_func_tables()
-{
-       DECODER_FUNCS [DECODER_FILE] = & FILE_DECODER_FUNCTIONS;
-       DECODER_FUNCS [DECODER_HTTP] = & HTTP_DECODER_FUNCTIONS;
-}
-
-static decoder_t source_to_decoder_type (const char *source)
-{
-       return strncasecmp(source, "http://", 7) ? DECODER_FILE : DECODER_HTTP;
-}
-
-static void change_decoder_if_needed (decoder_t new_decoder_type, void **decoderp, decoder_funcs_t const ** fntabp)
-{
-       const decoder_funcs_t *new_fn_table = DECODER_FUNCS [new_decoder_type];
-       if (*fntabp != new_fn_table) {
-               (*fntabp)->safe_decoder_delete(*decoderp);
-               *fntabp = new_fn_table;
-               *decoderp = new_fn_table -> new_decoder();
+               safe_decoder_finish_(decoder);
+               FLAC__stream_decoder_delete(decoder);
        }
 }
 
-FLAC__bool safe_decoder_init_(const char *filename, void **decoderp, decoder_funcs_t const ** fntabp)
+FLAC__StreamDecoderReadStatus http_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
 {
-       if(decoderp == 0 || *decoderp == 0)
-               return false;
-
-       (*fntabp)->safe_decoder_finish(*decoderp);
-
-       change_decoder_if_needed(source_to_decoder_type(filename), decoderp, fntabp);
-
-       {
-               decoder_funcs_t const *fntab = *fntabp;
-               void *decoder = *decoderp;
-
-               decoder = *decoderp;
-               fntab = *fntabp;
-
-               fntab -> set_md5_checking(decoder, false);
-               fntab -> set_source(decoder, filename);
-               fntab -> set_metadata_ignore_all(decoder);
-               fntab -> set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
-               fntab -> set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
-               fntab -> set_write_callback(decoder, write_callback_);
-               fntab -> set_metadata_callback(decoder, metadata_callback_);
-               fntab -> set_error_callback(decoder, error_callback_);
-               fntab -> set_client_data(decoder, &file_info_);
-               if(!fntab -> decoder_init(decoder))
-                       return false;
-
-               if(!fntab -> process_until_end_of_metadata(decoder))
-                       return false;
-       }
-
-       return true;
+       (void)decoder;
+       (void)client_data;
+       *bytes = flac_http_read(buffer, *bytes);
+       return *bytes ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
 }
 
-FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
-       file_info_struct *file_info = (file_info_struct *)client_data;
-       const unsigned channels = file_info->channels, wide_samples = frame->header.blocksize;
-       const unsigned bits_per_sample = file_info->bits_per_sample;
+       stream_data_struct *stream_data = (stream_data_struct *)client_data;
+       const unsigned channels = stream_data->channels, wide_samples = frame->header.blocksize;
+       const unsigned bits_per_sample = stream_data->bits_per_sample;
        FLAC__byte *sample_buffer_start;
 
        (void)decoder;
 
-       if(file_info->abort_flag)
+       if(stream_data->abort_flag)
                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
 
-       if((sample_buffer_last_ + wide_samples) > (SAMPLE_BUFFER_SIZE / (channels * file_info->sample_format_bytes_per_sample))) {
-               memmove(sample_buffer_, sample_buffer_ + sample_buffer_first_ * channels * file_info->sample_format_bytes_per_sample, (sample_buffer_last_ - sample_buffer_first_) * channels * file_info->sample_format_bytes_per_sample);
+       if((sample_buffer_last_ + wide_samples) > (SAMPLE_BUFFER_SIZE / (channels * stream_data->sample_format_bytes_per_sample))) {
+               memmove(sample_buffer_, sample_buffer_ + sample_buffer_first_ * channels * stream_data->sample_format_bytes_per_sample, (sample_buffer_last_ - sample_buffer_first_) * channels * stream_data->sample_format_bytes_per_sample);
                sample_buffer_last_ -= sample_buffer_first_;
                sample_buffer_first_ = 0;
        }
-       sample_buffer_start = sample_buffer_ + sample_buffer_last_ * channels * file_info->sample_format_bytes_per_sample;
-       if(file_info->has_replaygain && flac_cfg.output.replaygain.enable) {
+       sample_buffer_start = sample_buffer_ + sample_buffer_last_ * channels * stream_data->sample_format_bytes_per_sample;
+       if(stream_data->has_replaygain && flac_cfg.output.replaygain.enable) {
                FLAC__replaygain_synthesis__apply_gain(
                                sample_buffer_start,
                                !is_big_endian_host_,
-                               file_info->sample_format_bytes_per_sample == 1, /* unsigned_data_out */
+                               stream_data->sample_format_bytes_per_sample == 1, /* unsigned_data_out */
                                buffer,
                                wide_samples,
                                channels,
                                bits_per_sample,
-                               file_info->sample_format_bytes_per_sample * 8,
-                               file_info->replay_scale,
+                               stream_data->sample_format_bytes_per_sample * 8,
+                               stream_data->replay_scale,
                                flac_cfg.output.replaygain.hard_limit,
                                flac_cfg.output.resolution.replaygain.dither,
-                               &file_info->dither_context
+                               &stream_data->dither_context
                );
        }
        else if(is_big_endian_host_) {
@@ -773,7 +626,7 @@ FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__
                        wide_samples,
                        channels,
                        bits_per_sample,
-                       file_info->sample_format_bytes_per_sample * 8
+                       stream_data->sample_format_bytes_per_sample * 8
                );
        }
        else {
@@ -783,7 +636,7 @@ FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__
                        wide_samples,
                        channels,
                        bits_per_sample,
-                       file_info->sample_format_bytes_per_sample * 8
+                       stream_data->sample_format_bytes_per_sample * 8
                );
        }
 
@@ -792,35 +645,35 @@ FLAC__StreamDecoderWriteStatus write_callback_(const void *decoder, const FLAC__
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
 
-void metadata_callback_(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
-       file_info_struct *file_info = (file_info_struct *)client_data;
+       stream_data_struct *stream_data = (stream_data_struct *)client_data;
        (void)decoder;
        if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
-               file_info->total_samples = metadata->data.stream_info.total_samples;
-               file_info->bits_per_sample = metadata->data.stream_info.bits_per_sample;
-               file_info->channels = metadata->data.stream_info.channels;
-               file_info->sample_rate = metadata->data.stream_info.sample_rate;
+               stream_data->total_samples = metadata->data.stream_info.total_samples;
+               stream_data->bits_per_sample = metadata->data.stream_info.bits_per_sample;
+               stream_data->channels = metadata->data.stream_info.channels;
+               stream_data->sample_rate = metadata->data.stream_info.sample_rate;
                {
-                       FLAC__uint64 l = (FLAC__uint64)((double)file_info->total_samples / (double)file_info->sample_rate * 1000.0 + 0.5);
+                       FLAC__uint64 l = (FLAC__uint64)((double)stream_data->total_samples / (double)stream_data->sample_rate * 1000.0 + 0.5);
                        if (l > INT_MAX)
                                l = INT_MAX;
-                       file_info->length_in_msec = (int)l;
+                       stream_data->length_in_msec = (int)l;
                }
        }
        else if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
                double gain, peak;
                if(grabbag__replaygain_load_from_vorbiscomment(metadata, flac_cfg.output.replaygain.album_mode, /*strict=*/false, &gain, &peak)) {
-                       file_info->has_replaygain = true;
-                       file_info->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)flac_cfg.output.replaygain.preamp, /*prevent_clipping=*/!flac_cfg.output.replaygain.hard_limit);
+                       stream_data->has_replaygain = true;
+                       stream_data->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)flac_cfg.output.replaygain.preamp, /*prevent_clipping=*/!flac_cfg.output.replaygain.hard_limit);
                }
        }
 }
 
-void error_callback_(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
-       file_info_struct *file_info = (file_info_struct *)client_data;
+       stream_data_struct *stream_data = (stream_data_struct *)client_data;
        (void)decoder;
        if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
-               file_info->abort_flag = true;
+               stream_data->abort_flag = true;
 }
index b3e30ec..28457a6 100644 (file)
@@ -23,8 +23,8 @@
 #include "share/grabbag.h"
 #include "share/replaygain_analysis.h"
 #include "FLAC/assert.h"
-#include "FLAC/file_decoder.h"
 #include "FLAC/metadata.h"
+#include "FLAC/stream_decoder.h"
 #include <locale.h>
 #include <math.h>
 #include <stdio.h>
@@ -271,7 +271,7 @@ typedef struct {
        FLAC__bool error;
 } DecoderInstance;
 
-static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
        DecoderInstance *instance = (DecoderInstance*)client_data;
        const unsigned bits_per_sample = frame->header.bits_per_sample;
@@ -300,7 +300,7 @@ static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *d
                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
 }
 
-static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        DecoderInstance *instance = (DecoderInstance*)client_data;
 
@@ -323,7 +323,7 @@ static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__Str
        }
 }
 
-static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
        DecoderInstance *instance = (DecoderInstance*)client_data;
 
@@ -335,7 +335,7 @@ static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecode
 const char *grabbag__replaygain_analyze_file(const char *filename, float *title_gain, float *title_peak)
 {
        DecoderInstance instance;
-       FLAC__FileDecoder *decoder = FLAC__file_decoder_new();
+       FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new();
 
        if(0 == decoder)
                return "memory allocation error";
@@ -343,27 +343,21 @@ const char *grabbag__replaygain_analyze_file(const char *filename, float *title_
        instance.error = false;
 
        /* It does these three by default but lets be explicit: */
-       FLAC__file_decoder_set_md5_checking(decoder, false);
-       FLAC__file_decoder_set_metadata_ignore_all(decoder);
-       FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
-
-       FLAC__file_decoder_set_filename(decoder, filename);
-       FLAC__file_decoder_set_write_callback(decoder, write_callback_);
-       FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
-       FLAC__file_decoder_set_error_callback(decoder, error_callback_);
-       FLAC__file_decoder_set_client_data(decoder, &instance);
-
-       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
-               FLAC__file_decoder_delete(decoder);
+       FLAC__stream_decoder_set_md5_checking(decoder, false);
+       FLAC__stream_decoder_set_metadata_ignore_all(decoder);
+       FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
+
+       if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &instance) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+               FLAC__stream_decoder_delete(decoder);
                return "initializing decoder";
        }
 
-       if(!FLAC__file_decoder_process_until_end_of_file(decoder) || instance.error) {
-               FLAC__file_decoder_delete(decoder);
+       if(!FLAC__stream_decoder_process_until_end_of_stream(decoder) || instance.error) {
+               FLAC__stream_decoder_delete(decoder);
                return "decoding file";
        }
 
-       FLAC__file_decoder_delete(decoder);
+       FLAC__stream_decoder_delete(decoder);
 
        grabbag__replaygain_get_title(title_gain, title_peak);
 
index 7893eb1..1264420 100644 (file)
@@ -51,8 +51,10 @@ FLAC__bool grabbag__seektable_convert_specification_to_template(const char *spec
                                        if(0 != spec_has_real_points)
                                                *spec_has_real_points = true;
                                        if(!only_explicit_placeholders) {
-                                               if(!FLAC__metadata_object_seektable_template_append_spaced_points(seektable_template, atoi(pt), total_samples_to_encode))
-                                                       return false;
+                                               const int n = (unsigned)atoi(pt);
+                                               if(n > 0)
+                                                       if(!FLAC__metadata_object_seektable_template_append_spaced_points(seektable_template, (unsigned)n, total_samples_to_encode))
+                                                               return false;
                                        }
                                }
                        }
@@ -62,16 +64,14 @@ FLAC__bool grabbag__seektable_convert_specification_to_template(const char *spec
                                        if(0 != spec_has_real_points)
                                                *spec_has_real_points = true;
                                        if(!only_explicit_placeholders) {
-                                               double sec = atof(pt);
+                                               const double sec = atof(pt);
                                                if(sec > 0.0) {
-#if defined _MSC_VER || defined __MINGW32__
-                                                       /* with MSVC you have to spoon feed it the casting */
-                                                       unsigned n = (unsigned)((double)(FLAC__int64)total_samples_to_encode / (sec * (double)sample_rate));
-#else
-                                                       unsigned n = (unsigned)((double)total_samples_to_encode / (sec * (double)sample_rate));
-#endif
-                                                       if(!FLAC__metadata_object_seektable_template_append_spaced_points(seektable_template, n, total_samples_to_encode))
-                                                               return false;
+                                                       unsigned samples = (unsigned)(sec * (double)sample_rate);
+                                                       if(samples > 0) {
+                                                               /* +1 for the initial point at sample 0 */
+                                                               if(!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(seektable_template, samples, total_samples_to_encode))
+                                                                       return false;
+                                                       }
                                                }
                                        }
                                }
@@ -80,9 +80,15 @@ FLAC__bool grabbag__seektable_convert_specification_to_template(const char *spec
                                if(0 != spec_has_real_points)
                                        *spec_has_real_points = true;
                                if(!only_explicit_placeholders) {
-                                       FLAC__uint64 n = (unsigned)atoi(pt);
-                                       if(!FLAC__metadata_object_seektable_template_append_point(seektable_template, n))
-                                               return false;
+                                       char *endptr;
+#ifdef _MSC_VER
+                                       const FLAC__int64 n = (FLAC__int64)strtol(pt, &endptr, 10); /* [2G limit] */
+#else
+                                       const FLAC__int64 n = (FLAC__int64)strtoll(pt, &endptr, 10);
+#endif
+                                       if(n > 0 || (endptr > pt && *endptr == ';'))
+                                               if(!FLAC__metadata_object_seektable_template_append_point(seektable_template, (FLAC__uint64)n))
+                                                       return false;
                                }
                        }
                }
index 2647faf..c4db1d6 100644 (file)
 
 EXTRA_DIST = \
        Makefile.lite \
-       README \
        test_libFLAC++.dsp
 
 noinst_PROGRAMS = test_libFLAC++
 test_libFLAC___LDADD = \
        $(top_builddir)/src/share/grabbag/libgrabbag.la \
        $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+       $(top_builddir)/src/test_libs_common/libtest_libs_common.la \
        $(top_builddir)/src/libFLAC++/libFLAC++.la \
        $(top_builddir)/src/libFLAC/libFLAC.la \
        -lm
 test_libFLAC___SOURCES = \
        decoders.cpp \
        encoders.cpp \
-       file_utils.c \
        main.cpp \
        metadata.cpp \
        metadata_manip.cpp \
        metadata_object.cpp \
-       metadata_utils.c \
        decoders.h \
        encoders.h \
-       file_utils.h \
-       metadata.h \
-       metadata_utils.h
+       metadata.h
index e9a32c9..dacf49b 100644 (file)
@@ -27,14 +27,11 @@ PROGRAM_NAME = test_libFLAC++
 INCLUDES = -I$(topdir)/include
 
 ifeq ($(DARWIN_BUILD),yes)
-EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libreplaygain_analysis.a $(libdir)/libFLAC++.a $(libdir)/libFLAC.a -lm
+EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libreplaygain_analysis.a $(libdir)/libtest_libs_common.a $(libdir)/libFLAC++.a $(libdir)/libFLAC.a -lm
 else
-LIBS = -lgrabbag -lreplaygain_analysis -lFLAC++ -lFLAC -lm
+LIBS = -lgrabbag -lreplaygain_analysis -ltest_libs_common -lFLAC++ -lOggFLAC -lFLAC -L$(OGG_LIB_DIR) -logg -lm
 endif
 
-SRCS_C = \
-       file_utils.c \
-       metadata_utils.c
 SRCS_CPP = \
        decoders.cpp \
        encoders.cpp \
diff --git a/src/test_libFLAC++/README b/src/test_libFLAC++/README
deleted file mode 100644 (file)
index 3468225..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-NOTE: the following files are copied from the ../test_libFLAC directory:
-
-       file_utils.c
-       file_utils.h
-       metadata_utils.c
-       metadata_utils.h
-
-It's too much of a pain to make a convenience library for these and CVS
-can't do soft links, so we put up with having two copies of these sources.
-
-metadata_utils.c and metadata_utils.h have trivial changes for use in this
-package.
index a6ba8e7..486af3b 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #define ftello ftell
 #endif
 #include "decoders.h"
-extern "C" {
-#include "file_utils.h"
-#include "metadata_utils.h"
-}
 #include "FLAC/assert.h"
 #include "FLAC/metadata.h" // for ::FLAC__metadata_object_is_equal()
 #include "FLAC++/decoder.h"
 #include "share/grabbag.h"
+extern "C" {
+#include "test_libs_common/file_utils_flac.h"
+#include "test_libs_common/metadata_utils.h"
+}
 
 #ifdef _MSC_VER
 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
 #pragma warning ( disable : 4800 )
 #endif
 
+typedef enum {
+       LAYER_STREAM = 0, /* FLAC__stream_decoder_init_stream() without seeking */
+       LAYER_SEEKABLE_STREAM, /* FLAC__stream_decoder_init_stream() with seeking */
+       LAYER_FILE, /* FLAC__stream_decoder_init_FILE() */
+       LAYER_FILENAME /* FLAC__stream_decoder_init_file() */
+} Layer;
+
+static const char * const LayerString[] = {
+       "Stream",
+       "Seekable Stream",
+       "FILE*",
+       "Filename"
+};
+
 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
 static ::FLAC__StreamMetadata *expected_metadata_sequence_[8];
 static unsigned num_expected_;
@@ -52,6 +70,20 @@ static bool die_(const char *msg)
        return false;
 }
 
+static FLAC__bool die_s_(const char *msg, const FLAC::Decoder::Stream *decoder)
+{
+       FLAC::Decoder::Stream::State state = decoder->get_state();
+
+       if(msg)
+               printf("FAILED, %s", msg);
+       else
+               printf("FAILED");
+
+       printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
+
+       return false;
+}
+
 static void init_metadata_blocks_()
 {
        mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
@@ -84,42 +116,17 @@ static bool generate_file_()
 
 class DecoderCommon {
 public:
-       FILE *file_;
+       Layer layer_;
        unsigned current_metadata_number_;
        bool ignore_errors_;
        bool error_occurred_;
 
-       DecoderCommon(): file_(0), current_metadata_number_(0), ignore_errors_(false), error_occurred_(false) { }
-       ::FLAC__StreamDecoderReadStatus common_read_callback_(FLAC__byte buffer[], unsigned *bytes);
+       DecoderCommon(Layer layer): layer_(layer), current_metadata_number_(0), ignore_errors_(false), error_occurred_(false) { }
        ::FLAC__StreamDecoderWriteStatus common_write_callback_(const ::FLAC__Frame *frame);
        void common_metadata_callback_(const ::FLAC__StreamMetadata *metadata);
        void common_error_callback_(::FLAC__StreamDecoderErrorStatus status);
 };
 
-::FLAC__StreamDecoderReadStatus DecoderCommon::common_read_callback_(FLAC__byte buffer[], unsigned *bytes)
-{
-       if(error_occurred_)
-               return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT;
-
-       if(feof(file_))
-               return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-       else if(*bytes > 0) {
-               unsigned bytes_read = ::fread(buffer, 1, *bytes, file_);
-               if(bytes_read == 0) {
-                       if(feof(file_))
-                               return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-                       else
-                               return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-               }
-               else {
-                       *bytes = bytes_read;
-                       return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-               }
-       }
-       else
-               return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
-}
-
 ::FLAC__StreamDecoderWriteStatus DecoderCommon::common_write_callback_(const ::FLAC__Frame *frame)
 {
        if(error_occurred_)
@@ -167,23 +174,107 @@ void DecoderCommon::common_error_callback_(::FLAC__StreamDecoderErrorStatus stat
 
 class StreamDecoder : public FLAC::Decoder::Stream, public DecoderCommon {
 public:
-       StreamDecoder(): FLAC::Decoder::Stream(), DecoderCommon() { }
+       FILE *file_;
+
+       StreamDecoder(Layer layer): FLAC::Decoder::Stream(), DecoderCommon(layer), file_(0) { }
        ~StreamDecoder() { }
 
        // from FLAC::Decoder::Stream
        ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
+       ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
+       ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
+       ::FLAC__StreamDecoderLengthStatus 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);
        void error_callback(::FLAC__StreamDecoderErrorStatus status);
 
-       bool die(const char *msg = 0) const;
-
        bool test_respond();
 };
 
 ::FLAC__StreamDecoderReadStatus StreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
 {
-       return common_read_callback_(buffer, bytes);
+       const unsigned requested_bytes = *bytes;
+
+       if(error_occurred_)
+               return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+
+       if(feof(file_)) {
+               *bytes = 0;
+               return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+       }
+       else if(requested_bytes > 0) {
+               *bytes = ::fread(buffer, 1, requested_bytes, file_);
+               if(*bytes == 0) {
+                       if(feof(file_))
+                               return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+                       else
+                               return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+               }
+               else {
+                       return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+               }
+       }
+       else
+               return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
+}
+
+::FLAC__StreamDecoderSeekStatus StreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset)
+{
+       if(layer_ == LAYER_STREAM)
+               return ::FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+
+       if(error_occurred_)
+               return ::FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+
+       if(fseeko(file_, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
+               error_occurred_ = true;
+               return ::FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+       }
+
+       return ::FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+::FLAC__StreamDecoderTellStatus StreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
+{
+       if(layer_ == LAYER_STREAM)
+               return ::FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
+
+       if(error_occurred_)
+               return ::FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+
+       off_t offset = ftello(file_);
+       *absolute_byte_offset = (FLAC__uint64)offset;
+
+       if(offset < 0) {
+               error_occurred_ = true;
+               return ::FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+       }
+
+       return ::FLAC__STREAM_DECODER_TELL_STATUS_OK;
+}
+
+::FLAC__StreamDecoderLengthStatus StreamDecoder::length_callback(FLAC__uint64 *stream_length)
+{
+       if(layer_ == LAYER_STREAM)
+               return ::FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+
+       if(error_occurred_)
+               return ::FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+
+       *stream_length = (FLAC__uint64)flacfilesize_;
+       return ::FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+}
+
+bool StreamDecoder::eof_callback()
+{
+       if(layer_ == LAYER_STREAM)
+               return false;
+
+       if(error_occurred_)
+               return true;
+
+       return (bool)feof(file_);
 }
 
 ::FLAC__StreamDecoderWriteStatus StreamDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
@@ -203,25 +294,16 @@ void StreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
        common_error_callback_(status);
 }
 
-bool StreamDecoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
-
-       return false;
-}
-
 bool StreamDecoder::test_respond()
 {
+       if(!set_md5_checking(true)) {
+               printf("FAILED at set_md5_checking(), returned false\n");
+               return false;
+       }
+
        printf("testing init()... ");
-       if(init() != ::FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
-               return die();
+       if(init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+               return die_s_(0, this);
        printf("OK\n");
 
        current_metadata_number_ = 0;
@@ -246,17 +328,107 @@ bool StreamDecoder::test_respond()
        return true;
 }
 
-static bool test_stream_decoder()
+class FileDecoder : public FLAC::Decoder::File, public DecoderCommon {
+public:
+       FileDecoder(Layer layer): FLAC::Decoder::File(), DecoderCommon(layer) { }
+       ~FileDecoder() { }
+
+       // from FLAC::Decoder::Stream
+       ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
+       void metadata_callback(const ::FLAC__StreamMetadata *metadata);
+       void error_callback(::FLAC__StreamDecoderErrorStatus status);
+
+       bool test_respond();
+};
+
+::FLAC__StreamDecoderWriteStatus FileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
+{
+       (void)buffer;
+       return common_write_callback_(frame);
+}
+
+void FileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
+{
+       common_metadata_callback_(metadata);
+}
+
+void FileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
+{
+       common_error_callback_(status);
+}
+
+bool FileDecoder::test_respond()
+{
+       if(!set_md5_checking(true)) {
+               printf("FAILED at set_md5_checking(), returned false\n");
+               return false;
+       }
+
+       switch(layer_) {
+               case LAYER_FILE:
+                       {
+                               printf("opening FLAC file... ");
+                               FILE *file = ::fopen(flacfilename_, "rb");
+                               if(0 == file) {
+                                       printf("ERROR (%s)\n", strerror(errno));
+                                       return false;
+                               }
+                               printf("OK\n");
+
+                               printf("testing init()... ");
+                               if(init(file) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                                       return die_s_(0, this);
+                       }
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing init()... ");
+                       if(init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, this);
+                       break;
+               default:
+                       die_("internal error 001");
+                       return false;
+       }
+       printf("OK\n");
+
+       current_metadata_number_ = 0;
+
+       printf("testing process_until_end_of_stream()... ");
+       if(!process_until_end_of_stream()) {
+               State state = get_state();
+               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
+               return false;
+       }
+       printf("OK\n");
+
+       printf("testing finish()... ");
+       finish();
+       printf("OK\n");
+
+       return true;
+}
+
+
+static FLAC::Decoder::Stream *new_by_layer(Layer layer)
+{
+       if(layer < LAYER_FILE)
+               return new StreamDecoder(layer);
+       else
+               return new FileDecoder(layer);
+}
+
+static bool test_stream_decoder(Layer layer)
 {
-       StreamDecoder *decoder;
+       FLAC::Decoder::Stream *decoder;
+       bool expect;
 
-       printf("\n+++ libFLAC++ unit test: FLAC::Decoder::Stream\n\n");
+       printf("\n+++ libFLAC++ unit test: FLAC::Decoder::%s (layer: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer]);
 
        //
        // test new -> delete
        //
        printf("allocating decoder instance... ");
-       decoder = new StreamDecoder();
+       decoder = new_by_layer(layer);
        if(0 == decoder) {
                printf("FAILED, new returned NULL\n");
                return false;
@@ -278,7 +450,7 @@ static bool test_stream_decoder()
        // test new -> init -> delete
        //
        printf("allocating decoder instance... ");
-       decoder = new StreamDecoder();
+       decoder = new_by_layer(layer);
        if(0 == decoder) {
                printf("FAILED, new returned NULL\n");
                return false;
@@ -293,8 +465,25 @@ static bool test_stream_decoder()
        printf("OK\n");
 
        printf("testing init()... ");
-       if(decoder->init() != ::FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
-               return decoder->die();
+       switch(layer) {
+               case LAYER_STREAM:
+               case LAYER_SEEKABLE_STREAM:
+                       dynamic_cast<StreamDecoder*>(decoder)->file_ = stdin;
+                       if(decoder->init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILE:
+                       if(dynamic_cast<FLAC::Decoder::File*>(decoder)->init(stdin) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILENAME:
+                       if(dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               default:
+                       die_("internal error 006");
+                       return false;
+       }
        printf("OK\n");
 
        printf("freeing decoder instance... ");
@@ -308,7 +497,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &streaminfo_;
 
        printf("allocating decoder instance... ");
-       decoder = new StreamDecoder();
+       decoder = new_by_layer(layer);
        if(0 == decoder) {
                printf("FAILED, new returned NULL\n");
                return false;
@@ -322,57 +511,111 @@ static bool test_stream_decoder()
        }
        printf("OK\n");
 
-       printf("testing init()... ");
-       if(decoder->init() != ::FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
-               return decoder->die();
+       if(!decoder->set_md5_checking(true)) {
+               printf("FAILED at set_md5_checking(), returned false\n");
+               return false;
+       }
+
+       switch(layer) {
+               case LAYER_STREAM:
+               case LAYER_SEEKABLE_STREAM:
+                       printf("opening FLAC file... ");
+                       dynamic_cast<StreamDecoder*>(decoder)->file_ = ::fopen(flacfilename_, "rb");
+                       if(0 == dynamic_cast<StreamDecoder*>(decoder)->file_) {
+                               printf("ERROR (%s)\n", strerror(errno));
+                               return false;
+                       }
+                       printf("OK\n");
+
+                       printf("testing init()... ");
+                       if(decoder->init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILE:
+                       {
+                               printf("opening FLAC file... ");
+                               FILE *file = ::fopen(flacfilename_, "rb");
+                               if(0 == file) {
+                                       printf("ERROR (%s)\n", strerror(errno));
+                                       return false;
+                               }
+                               printf("OK\n");
+
+                               printf("testing init()... ");
+                               if(dynamic_cast<FLAC::Decoder::File*>(decoder)->init(file) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                                       return die_s_(0, decoder);
+                       }
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing init()... ");
+                       if(dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               default:
+                       die_("internal error 009");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing get_state()... ");
        FLAC::Decoder::Stream::State state = decoder->get_state();
        printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
 
-       decoder->current_metadata_number_ = 0;
-       decoder->ignore_errors_ = false;
-       decoder->error_occurred_ = false;
+       dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
+       dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
+       dynamic_cast<DecoderCommon*>(decoder)->error_occurred_ = false;
 
-       printf("opening FLAC file... ");
-       decoder->file_ = ::fopen(flacfilename_, "rb");
-       if(0 == decoder->file_) {
-               printf("ERROR (%s)\n", strerror(errno));
+       printf("testing get_md5_checking()... ");
+       if(!decoder->get_md5_checking()) {
+               printf("FAILED, returned false, expected true\n");
                return false;
        }
        printf("OK\n");
 
        printf("testing process_until_end_of_metadata()... ");
        if(!decoder->process_until_end_of_metadata())
-               return decoder->die("returned false");
+               return die_s_("returned false", decoder);
        printf("OK\n");
 
        printf("testing process_single()... ");
        if(!decoder->process_single())
-               return decoder->die("returned false");
+               return die_s_("returned false", decoder);
        printf("OK\n");
 
        printf("testing skip_single_frame()... ");
        if(!decoder->skip_single_frame())
-               return decoder->die("returned false");
+               return die_s_("returned false", decoder);
        printf("OK\n");
 
-       printf("testing flush()... ");
-       if(!decoder->flush())
-               return decoder->die("returned false");
-       printf("OK\n");
+       if(layer < LAYER_FILE) {
+               printf("testing flush()... ");
+               if(!decoder->flush())
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
 
-       decoder->ignore_errors_ = true;
-       printf("testing process_single()... ");
-       if(!decoder->process_single())
-               return decoder->die("returned false");
+               dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = true;
+               printf("testing process_single()... ");
+               if(!decoder->process_single())
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+               dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
+       }
+
+       expect = (layer != LAYER_STREAM);
+       printf("testing seek_absolute()... ");
+       if(decoder->seek_absolute(0) != expect)
+               return die_s_(expect? "returned false" : "returned true", decoder);
        printf("OK\n");
-       decoder->ignore_errors_ = false;
 
        printf("testing process_until_end_of_stream()... ");
        if(!decoder->process_until_end_of_stream())
-               return decoder->die("returned false");
+               return die_s_("returned false", decoder);
+       printf("OK\n");
+
+       expect = (layer != LAYER_STREAM);
+       printf("testing seek_absolute()... ");
+       if(decoder->seek_absolute(0) != expect)
+               return die_s_(expect? "returned false" : "returned true", decoder);
        printf("OK\n");
 
        printf("testing get_channels()... ");
@@ -408,8 +651,10 @@ static bool test_stream_decoder()
        printf("testing get_blocksize()... ");
        {
                unsigned blocksize = decoder->get_blocksize();
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
+               /* value could be anything since we're at the last block, so accept any reasonable answer */
+               printf("returned %u... %s\n", blocksize, blocksize>0? "OK" : "FAILED");
+               if(blocksize == 0)
+                       return false;
        }
 
        printf("testing get_channel_assignment()... ");
@@ -418,24 +663,29 @@ static bool test_stream_decoder()
                printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
        }
 
-       printf("testing reset()... ");
-       if(!decoder->reset())
-               return decoder->die("returned false");
-       printf("OK\n");
+       if(layer < LAYER_FILE) {
+               printf("testing reset()... ");
+               if(!decoder->reset())
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+
+               if(layer == LAYER_STREAM) {
+                       /* after a reset() we have to rewind the input ourselves */
+                       printf("rewinding input... ");
+                       if(fseeko(dynamic_cast<StreamDecoder*>(decoder)->file_, 0, SEEK_SET) < 0) {
+                               printf("FAILED, errno = %d\n", errno);
+                               return false;
+                       }
+                       printf("OK\n");
+               }
 
-       decoder->current_metadata_number_ = 0;
+               dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
 
-       printf("rewinding input... ");
-       if(fseeko(decoder->file_, 0, SEEK_SET) < 0) {
-               printf("FAILED, errno = %d\n", errno);
-               return false;
+               printf("testing process_until_end_of_stream()... ");
+               if(!decoder->process_until_end_of_stream())
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
        }
-       printf("OK\n");
-
-       printf("testing process_until_end_of_stream()... ");
-       if(!decoder->process_until_end_of_stream())
-               return decoder->die("returned false");
-       printf("OK\n");
 
        printf("testing finish()... ");
        decoder->finish();
@@ -462,7 +712,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -478,7 +728,7 @@ static bool test_stream_decoder()
 
        num_expected_ = 0;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -508,7 +758,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -537,7 +787,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -567,7 +817,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -603,7 +853,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -627,7 +877,7 @@ static bool test_stream_decoder()
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -652,7 +902,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &application1_;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -676,7 +926,7 @@ static bool test_stream_decoder()
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &application1_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -708,7 +958,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &application1_;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -745,7 +995,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -776,21 +1026,11 @@ static bool test_stream_decoder()
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       ::fclose(decoder->file_);
+       if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
+               ::fclose(dynamic_cast<StreamDecoder*>(decoder)->file_);
 
        printf("freeing decoder instance... ");
        delete decoder;
@@ -801,1382 +1041,23 @@ static bool test_stream_decoder()
        return true;
 }
 
-class SeekableStreamDecoder : public FLAC::Decoder::SeekableStream, public DecoderCommon {
-public:
-       SeekableStreamDecoder(): FLAC::Decoder::SeekableStream(), DecoderCommon() { }
-       ~SeekableStreamDecoder() { }
-
-       // from FLAC::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);
-       bool eof_callback();
-       ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
-       void metadata_callback(const ::FLAC__StreamMetadata *metadata);
-       void error_callback(::FLAC__StreamDecoderErrorStatus status);
-
-       bool die(const char *msg = 0) const;
-
-       bool test_respond();
-};
-
-::FLAC__SeekableStreamDecoderReadStatus SeekableStreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
-{
-       switch(common_read_callback_(buffer, bytes)) {
-               case ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE:
-                       return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-               case ::FLAC__STREAM_DECODER_READ_STATUS_ABORT:
-               case ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM:
-                       return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-               default:
-                       FLAC__ASSERT(0);
-                       return ::FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-       }
-}
-
-::FLAC__SeekableStreamDecoderSeekStatus SeekableStreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset)
-{
-       if(error_occurred_)
-               return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-
-       if(fseeko(file_, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
-               error_occurred_ = true;
-               return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-       }
-
-       return ::FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-::FLAC__SeekableStreamDecoderTellStatus SeekableStreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
+bool test_decoders()
 {
-       if(error_occurred_)
-               return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
+       init_metadata_blocks_();
 
-       off_t offset = ftello(file_);
-       *absolute_byte_offset = (FLAC__uint64)offset;
+       if(!generate_file_())
+               return false;
 
-       if(offset < 0) {
-               error_occurred_ = true;
-               return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-       }
-
-       return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
-}
-
-::FLAC__SeekableStreamDecoderLengthStatus SeekableStreamDecoder::length_callback(FLAC__uint64 *stream_length)
-{
-       if(error_occurred_)
-               return ::FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
-
-       *stream_length = (FLAC__uint64)flacfilesize_;
-       return ::FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
-}
-
-bool SeekableStreamDecoder::eof_callback()
-{
-       if(error_occurred_)
-               return true;
-
-       return (bool)feof(file_);
-}
-
-::FLAC__StreamDecoderWriteStatus SeekableStreamDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
-{
-       (void)buffer;
-
-       return common_write_callback_(frame);
-}
-
-void SeekableStreamDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
-{
-       common_metadata_callback_(metadata);
-}
-
-void SeekableStreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
-{
-       common_error_callback_(status);
-}
-
-bool SeekableStreamDecoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state), state.as_cstring());
-       if(state == ::FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
-               FLAC::Decoder::Stream::State state_ = get_stream_decoder_state();
-               printf("      stream decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state_), state_.as_cstring());
-       }
-
-       return false;
-}
-
-bool SeekableStreamDecoder::test_respond()
-{
-       if(!set_md5_checking(true)) {
-               printf("FAILED at set_md5_checking(), returned false\n");
-               return false;
-       }
-
-       printf("testing init()... ");
-       if(init() != ::FLAC__SEEKABLE_STREAM_DECODER_OK)
-               return die();
-       printf("OK\n");
-
-       current_metadata_number_ = 0;
-
-       if(fseeko(file_, 0, SEEK_SET) < 0) {
-               printf("FAILED rewinding input, errno = %d\n", errno);
-               return false;
-       }
-
-       printf("testing process_until_end_of_stream()... ");
-       if(!process_until_end_of_stream()) {
-               State state = get_state();
-               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state), state.as_cstring());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       finish();
-       printf("OK\n");
-
-       return true;
-}
-
-static bool test_seekable_stream_decoder()
-{
-       SeekableStreamDecoder *decoder;
-
-       printf("\n+++ libFLAC++ unit test: FLAC::Decoder::SeekableStream\n\n");
-
-       //
-       // test new -> delete
-       //
-       printf("allocating decoder instance... ");
-       decoder = new SeekableStreamDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       //
-       // test new -> init -> delete
-       //
-       printf("allocating decoder instance... ");
-       decoder = new SeekableStreamDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(decoder->init() != ::FLAC__SEEKABLE_STREAM_DECODER_OK)
-               return decoder->die();
-       printf("OK\n");
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       //
-       // test normal usage
-       //
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-
-       printf("allocating decoder instance... ");
-       decoder = new SeekableStreamDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_md5_checking()... ");
-       if(!decoder->set_md5_checking(true)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(decoder->init() != ::FLAC__SEEKABLE_STREAM_DECODER_OK)
-               return decoder->die();
-       printf("OK\n");
-
-       printf("testing get_state()... ");
-       FLAC::Decoder::SeekableStream::State state = decoder->get_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state), state.as_cstring());
-
-       printf("testing get_stream_decoder_state()... ");
-       FLAC::Decoder::Stream::State state_ = decoder->get_stream_decoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state_), state_.as_cstring());
-
-       decoder->current_metadata_number_ = 0;
-       decoder->ignore_errors_ = false;
-       decoder->error_occurred_ = false;
-
-       printf("opening FLAC file... ");
-       decoder->file_ = ::fopen(flacfilename_, "rb");
-       if(0 == decoder->file_) {
-               printf("ERROR (%s)\n", strerror(errno));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_md5_checking()... ");
-       if(!decoder->get_md5_checking()) {
-               printf("FAILED, returned false, expected true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing process_until_end_of_metadata()... ");
-       if(!decoder->process_until_end_of_metadata())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_single()... ");
-       if(!decoder->process_single())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing skip_single_frame()... ");
-       if(!decoder->skip_single_frame())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing flush()... ");
-       if(!decoder->flush())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       decoder->ignore_errors_ = true;
-       printf("testing process_single()... ");
-       if(!decoder->process_single())
-               return decoder->die("returned false");
-       printf("OK\n");
-       decoder->ignore_errors_ = false;
-
-       printf("testing seek_absolute()... ");
-       if(!decoder->seek_absolute(0))
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_until_end_of_stream()... ");
-       if(!decoder->process_until_end_of_stream())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing get_channels()... ");
-       {
-               unsigned channels = decoder->get_channels();
-               if(channels != streaminfo_.data.stream_info.channels) {
-                       printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_bits_per_sample()... ");
-       {
-               unsigned bits_per_sample = decoder->get_bits_per_sample();
-               if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
-                       printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_sample_rate()... ");
-       {
-               unsigned sample_rate = decoder->get_sample_rate();
-               if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
-                       printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_blocksize()... ");
-       {
-               unsigned blocksize = decoder->get_blocksize();
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
-       }
-
-       printf("testing get_channel_assignment()... ");
-       {
-               ::FLAC__ChannelAssignment ca = decoder->get_channel_assignment();
-               printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
-       }
-
-       printf("testing reset()... ");
-       if(!decoder->reset())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       decoder->current_metadata_number_ = 0;
-
-       printf("rewinding input... ");
-       if(fseeko(decoder->file_, 0, SEEK_SET) < 0) {
-               printf("FAILED, errno = %d\n", errno);
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing process_until_end_of_stream()... ");
-       if(!decoder->process_until_end_of_stream())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       decoder->finish();
-       printf("OK\n");
-
-       /*
-        * respond all
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore VORBIS_COMMENT
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(VORBIS_COMMENT)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(APPLICATION)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #2)... ");
-       if(!decoder->set_metadata_ignore_application(application2_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond VORBIS_COMMENT
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(VORBIS_COMMENT)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(APPLICATION)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #2)... ");
-       if(!decoder->set_metadata_respond_application(application2_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION, respond APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(APPLICATION)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(APPLICATION)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       ::fclose(decoder->file_);
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-class FileDecoder : public FLAC::Decoder::File, public DecoderCommon {
-public:
-       FileDecoder(): FLAC::Decoder::File(), DecoderCommon() { }
-       ~FileDecoder() { }
-
-       // from FLAC::Decoder::File
-       ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
-       void metadata_callback(const ::FLAC__StreamMetadata *metadata);
-       void error_callback(::FLAC__StreamDecoderErrorStatus status);
-
-       bool die(const char *msg = 0) const;
-
-       bool test_respond();
-};
-
-::FLAC__StreamDecoderWriteStatus FileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
-{
-       (void)buffer;
-       return common_write_callback_(frame);
-}
-
-void FileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
-{
-       common_metadata_callback_(metadata);
-}
-
-void FileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
-{
-       common_error_callback_(status);
-}
-
-bool FileDecoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::FLAC__FileDecoderState)state), state.as_cstring());
-       if(state == ::FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) {
-               FLAC::Decoder::SeekableStream::State state_ = get_seekable_stream_decoder_state();
-               printf("      seekable stream decoder state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state_), state_.as_cstring());
-               if(state_ == ::FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
-                       FLAC::Decoder::Stream::State state__ = get_stream_decoder_state();
-                       printf("      stream decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state__), state__.as_cstring());
-               }
-       }
-
-       return false;
-}
-
-bool FileDecoder::test_respond()
-{
-       if(!set_filename(flacfilename_)) {
-               printf("FAILED at set_filename(), returned false\n");
-               return false;
-       }
-
-       if(!set_md5_checking(true)) {
-               printf("FAILED at set_md5_checking(), returned false\n");
-               return false;
-       }
-
-       printf("testing init()... ");
-       if(init() != ::FLAC__FILE_DECODER_OK)
-               return die();
-       printf("OK\n");
-
-       current_metadata_number_ = 0;
-
-       printf("testing process_until_end_of_file()... ");
-       if(!process_until_end_of_file()) {
-               State state = get_state();
-               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__FileDecoderState)state), state.as_cstring());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       finish();
-       printf("OK\n");
-
-       return true;
-}
-
-static bool test_file_decoder()
-{
-       FileDecoder *decoder;
-
-       printf("\n+++ libFLAC++ unit test: FLAC::Decoder::File\n\n");
-
-       //
-       // test new -> delete
-       //
-       printf("allocating decoder instance... ");
-       decoder = new FileDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       //
-       // test new -> init -> delete
-       //
-       printf("allocating decoder instance... ");
-       decoder = new FileDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(decoder->init() != ::FLAC__FILE_DECODER_OK)
-               return decoder->die();
-       printf("OK\n");
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       //
-       // test normal usage
-       //
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-
-       printf("allocating decoder instance... ");
-       decoder = new FileDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_filename()... ");
-       if(!decoder->set_filename(flacfilename_)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_md5_checking()... ");
-       if(!decoder->set_md5_checking(true)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(decoder->init() != ::FLAC__FILE_DECODER_OK)
-               return decoder->die();
-       printf("OK\n");
-
-       printf("testing get_state()... ");
-       FLAC::Decoder::File::State state = decoder->get_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__FileDecoderState)state), state.as_cstring());
-
-       printf("testing get_seekable_stream_decoder_state()... ");
-       FLAC::Decoder::SeekableStream::State state_ = decoder->get_seekable_stream_decoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state_), state_.as_cstring());
-
-       printf("testing get_stream_decoder_state()... ");
-       FLAC::Decoder::Stream::State state__ = decoder->get_stream_decoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state__), state__.as_cstring());
-
-       decoder->current_metadata_number_ = 0;
-       decoder->ignore_errors_ = false;
-       decoder->error_occurred_ = false;
-
-       printf("testing get_md5_checking()... ");
-       if(!decoder->get_md5_checking()) {
-               printf("FAILED, returned false, expected true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing process_until_end_of_metadata()... ");
-       if(!decoder->process_until_end_of_metadata())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_single()... ");
-       if(!decoder->process_single())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing skip_single_frame()... ");
-       if(!decoder->skip_single_frame())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing seek_absolute()... ");
-       if(!decoder->seek_absolute(0))
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_until_end_of_file()... ");
-       if(!decoder->process_until_end_of_file())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing get_channels()... ");
-       {
-               unsigned channels = decoder->get_channels();
-               if(channels != streaminfo_.data.stream_info.channels) {
-                       printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_bits_per_sample()... ");
-       {
-               unsigned bits_per_sample = decoder->get_bits_per_sample();
-               if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
-                       printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_sample_rate()... ");
-       {
-               unsigned sample_rate = decoder->get_sample_rate();
-               if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
-                       printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_blocksize()... ");
-       {
-               unsigned blocksize = decoder->get_blocksize();
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
-       }
-
-       printf("testing get_channel_assignment()... ");
-       {
-               ::FLAC__ChannelAssignment ca = decoder->get_channel_assignment();
-               printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
-       }
-
-       printf("testing finish()... ");
-       decoder->finish();
-       printf("OK\n");
-
-       /*
-        * respond all
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore VORBIS_COMMENT
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(VORBIS_COMMENT)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(APPLICATION)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #2)... ");
-       if(!decoder->set_metadata_ignore_application(application2_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond VORBIS_COMMENT
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(VORBIS_COMMENT)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(APPLICATION)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #2)... ");
-       if(!decoder->set_metadata_respond_application(application2_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION, respond APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(APPLICATION)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(APPLICATION)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-bool test_decoders()
-{
-       init_metadata_blocks_();
-
-       if(!generate_file_())
+       if(!test_stream_decoder(LAYER_STREAM))
                return false;
 
-       if(!test_stream_decoder())
+       if(!test_stream_decoder(LAYER_SEEKABLE_STREAM))
                return false;
 
-       if(!test_seekable_stream_decoder())
+       if(!test_stream_decoder(LAYER_FILE))
                return false;
 
-       if(!test_file_decoder())
+       if(!test_stream_decoder(LAYER_FILENAME))
                return false;
 
        (void) grabbag__file_remove_file(flacfilename_);
index 880e3bc..24845b8 100644 (file)
  */
 
 #include "encoders.h"
-extern "C" {
-#include "file_utils.h"
-#include "metadata_utils.h"
-}
 #include "FLAC/assert.h"
 #include "FLAC++/encoder.h"
+extern "C" {
+#include "test_libs_common/file_utils_flac.h"
+#include "test_libs_common/metadata_utils.h"
+}
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+typedef enum {
+       LAYER_STREAM = 0, /* FLAC__stream_encoder_init_stream() without seeking */
+       LAYER_SEEKABLE_STREAM, /* FLAC__stream_encoder_init_stream() with seeking */
+       LAYER_FILE, /* FLAC__stream_encoder_init_FILE() */
+       LAYER_FILENAME /* FLAC__stream_encoder_init_file() */
+} Layer;
+
+static const char * const LayerString[] = {
+       "Stream",
+       "Seekable Stream",
+       "FILE*",
+       "Filename"
+};
+
 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
 static ::FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_ };
 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
 static const char *flacfilename_ = "metadata.flac";
 
+static FLAC__bool die_(const char *msg)
+{
+       printf("ERROR: %s\n", msg);
+       return false;
+}
+
+static bool die_s_(const char *msg, const FLAC::Encoder::Stream *encoder)
+{
+       FLAC::Encoder::Stream::State state = encoder->get_state();
+
+       if(msg)
+               printf("FAILED, %s", msg);
+       else
+               printf("FAILED");
+
+       printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring());
+       if(state == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
+               FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
+               printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
+       }
+
+       return false;
+}
+
 static void init_metadata_blocks_()
 {
        mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
@@ -44,14 +83,16 @@ static void free_metadata_blocks_()
 
 class StreamEncoder : public FLAC::Encoder::Stream {
 public:
-       StreamEncoder(): FLAC::Encoder::Stream() { }
+       Layer layer_;
+
+       StreamEncoder(Layer layer): FLAC::Encoder::Stream(), layer_(layer) { }
        ~StreamEncoder() { }
 
        // from FLAC::Encoder::Stream
        ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame);
+       ::FLAC__StreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
+       ::FLAC__StreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
        void metadata_callback(const ::FLAC__StreamMetadata *metadata);
-
-       bool die(const char *msg = 0) const;
 };
 
 ::FLAC__StreamEncoderWriteStatus StreamEncoder::write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame)
@@ -61,40 +102,61 @@ public:
        return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
 }
 
+::FLAC__StreamEncoderSeekStatus StreamEncoder::seek_callback(FLAC__uint64 absolute_byte_offset)
+{
+       (void)absolute_byte_offset;
+
+       return layer_==LAYER_STREAM? ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED : ::FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+}
+
+::FLAC__StreamEncoderTellStatus StreamEncoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
+{
+       *absolute_byte_offset = 0;
+
+       return layer_==LAYER_STREAM? ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED : ::FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+}
+
 void StreamEncoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
 {
        (void)metadata;
 }
 
-bool StreamEncoder::die(const char *msg) const
-{
-       State state = get_state();
+class FileEncoder : public FLAC::Encoder::File {
+public:
+       Layer layer_;
 
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
+       FileEncoder(Layer layer): FLAC::Encoder::File(), layer_(layer) { }
+       ~FileEncoder() { }
 
-       printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring());
-       if(state == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-               FLAC::Decoder::Stream::State dstate = get_verify_decoder_state();
-               printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-       }
+       // from FLAC::Encoder::File
+       void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate);
+};
 
-       return false;
+void FileEncoder::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate)
+{
+       (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate;
+}
+
+static FLAC::Encoder::Stream *new_by_layer(Layer layer)
+{
+       if(layer < LAYER_FILE)
+               return new StreamEncoder(layer);
+       else
+               return new FileEncoder(layer);
 }
 
-static bool test_stream_encoder()
+static bool test_stream_encoder(Layer layer)
 {
-       StreamEncoder *encoder;
+       FLAC::Encoder::Stream *encoder;
+       FILE *file = 0;
        FLAC__int32 samples[1024];
        FLAC__int32 *samples_array[1] = { samples };
        unsigned i;
 
-       printf("\n+++ libFLAC++ unit test: FLAC::Encoder::Stream\n\n");
+       printf("\n+++ libFLAC++ unit test: FLAC::Encoder::%s (layer: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer]);
 
        printf("allocating encoder instance... ");
-       encoder = new StreamEncoder();
+       encoder = new_by_layer(layer);
        if(0 == encoder) {
                printf("FAILED, new returned NULL\n");
                return false;
@@ -110,97 +172,123 @@ static bool test_stream_encoder()
 
        printf("testing set_verify()... ");
        if(!encoder->set_verify(true))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_streamable_subset()... ");
        if(!encoder->set_streamable_subset(true))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_do_mid_side_stereo()... ");
        if(!encoder->set_do_mid_side_stereo(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_loose_mid_side_stereo()... ");
        if(!encoder->set_loose_mid_side_stereo(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_channels()... ");
        if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_bits_per_sample()... ");
        if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_sample_rate()... ");
        if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_blocksize()... ");
        if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_max_lpc_order()... ");
        if(!encoder->set_max_lpc_order(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_qlp_coeff_precision()... ");
        if(!encoder->set_qlp_coeff_precision(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_do_qlp_coeff_prec_search()... ");
        if(!encoder->set_do_qlp_coeff_prec_search(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_do_escape_coding()... ");
        if(!encoder->set_do_escape_coding(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_do_exhaustive_model_search()... ");
        if(!encoder->set_do_exhaustive_model_search(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_min_residual_partition_order()... ");
        if(!encoder->set_min_residual_partition_order(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_max_residual_partition_order()... ");
        if(!encoder->set_max_residual_partition_order(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_rice_parameter_search_dist()... ");
        if(!encoder->set_rice_parameter_search_dist(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_total_samples_estimate()... ");
        if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_metadata()... ");
        if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
-               return encoder->die("returned false");
-       printf("OK\n");
+               return die_s_("returned false", encoder);
+       printf("OK\n");
+
+       switch(layer) {
+               case LAYER_STREAM:
+               case LAYER_SEEKABLE_STREAM:
+                       printf("testing init()... ");
+                       if(encoder->init() != ::FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_FILE:
+                       printf("opening file for FLAC output... ");
+                       file = ::fopen(flacfilename_, "w+b");
+                       if(0 == file) {
+                               printf("ERROR (%s)\n", strerror(errno));
+                               return false;
+                       }
+                       printf("OK\n");
 
-       printf("testing init()... ");
-       if(encoder->init() != ::FLAC__STREAM_ENCODER_OK)
-               return encoder->die();
+                       printf("testing init()... ");
+                       if(dynamic_cast<FLAC::Encoder::File*>(encoder)->init(file) != ::FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing init()... ");
+                       if(dynamic_cast<FLAC::Encoder::File*>(encoder)->init(flacfilename_) != ::FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               default:
+                       die_("internal error 001");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing get_state()... ");
@@ -347,12 +435,12 @@ static bool test_stream_encoder()
 
        printf("testing process()... ");
        if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing process_interleaved()... ");
        if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing finish()... ");
@@ -368,699 +456,20 @@ static bool test_stream_encoder()
        return true;
 }
 
-class SeekableStreamEncoder : public FLAC::Encoder::SeekableStream {
-public:
-       SeekableStreamEncoder(): FLAC::Encoder::SeekableStream() { }
-       ~SeekableStreamEncoder() { }
-
-       // from FLAC::Encoder::SeekableStream
-       ::FLAC__SeekableStreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
-       ::FLAC__SeekableStreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
-       ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame);
-
-       bool die(const char *msg = 0) const;
-};
-
-::FLAC__SeekableStreamEncoderSeekStatus SeekableStreamEncoder::seek_callback(FLAC__uint64 absolute_byte_offset)
-{
-       (void)absolute_byte_offset;
-
-       return ::FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
-}
-
-::FLAC__SeekableStreamEncoderTellStatus SeekableStreamEncoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
-{
-       *absolute_byte_offset = 0;
-
-       return ::FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK;
-}
-
-::FLAC__StreamEncoderWriteStatus SeekableStreamEncoder::write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame)
-{
-       (void)buffer, (void)bytes, (void)samples, (void)current_frame;
-
-       return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-}
-
-bool SeekableStreamEncoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamEncoderState)state), state.as_cstring());
-       if(state == ::FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) {
-               FLAC::Encoder::Stream::State state_ = get_stream_encoder_state();
-               printf("      stream encoder state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
-               if(state_ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                       FLAC::Decoder::Stream::State dstate = get_verify_decoder_state();
-                       printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-               }
-       }
-
-       return false;
-}
-
-static bool test_seekable_stream_encoder()
+bool test_encoders()
 {
-       SeekableStreamEncoder *encoder;
-       FLAC__int32 samples[1024];
-       FLAC__int32 *samples_array[1] = { samples };
-       unsigned i;
-
-       printf("\n+++ libFLAC++ unit test: FLAC::Encoder::SeekableStream\n\n");
-
-       printf("allocating encoder instance... ");
-       encoder = new SeekableStreamEncoder();
-       if(0 == encoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!encoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_verify()... ");
-       if(!encoder->set_verify(true))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_streamable_subset()... ");
-       if(!encoder->set_streamable_subset(true))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_mid_side_stereo()... ");
-       if(!encoder->set_do_mid_side_stereo(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_loose_mid_side_stereo()... ");
-       if(!encoder->set_loose_mid_side_stereo(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_channels()... ");
-       if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_bits_per_sample()... ");
-       if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_sample_rate()... ");
-       if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_blocksize()... ");
-       if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_max_lpc_order()... ");
-       if(!encoder->set_max_lpc_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_qlp_coeff_precision()... ");
-       if(!encoder->set_qlp_coeff_precision(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_qlp_coeff_prec_search()... ");
-       if(!encoder->set_do_qlp_coeff_prec_search(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_escape_coding()... ");
-       if(!encoder->set_do_escape_coding(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_exhaustive_model_search()... ");
-       if(!encoder->set_do_exhaustive_model_search(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_min_residual_partition_order()... ");
-       if(!encoder->set_min_residual_partition_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_max_residual_partition_order()... ");
-       if(!encoder->set_max_residual_partition_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_rice_parameter_search_dist()... ");
-       if(!encoder->set_rice_parameter_search_dist(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_total_samples_estimate()... ");
-       if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_metadata()... ");
-       if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(encoder->init() != ::FLAC__SEEKABLE_STREAM_ENCODER_OK)
-               return encoder->die();
-       printf("OK\n");
-
-       printf("testing get_state()... ");
-       FLAC::Encoder::SeekableStream::State state = encoder->get_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamEncoderState)state), state.as_cstring());
-
-       printf("testing get_stream_encoder_state()... ");
-       FLAC::Encoder::Stream::State state_ = encoder->get_stream_encoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
-
-       printf("testing get_verify_decoder_state()... ");
-       FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-
-       {
-               FLAC__uint64 absolute_sample;
-               unsigned frame_number;
-               unsigned channel;
-               unsigned sample;
-               FLAC__int32 expected;
-               FLAC__int32 got;
-
-               printf("testing get_verify_decoder_error_stats()... ");
-               encoder->get_verify_decoder_error_stats(&absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               printf("OK\n");
-       }
-
-       printf("testing get_verify()... ");
-       if(encoder->get_verify() != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_streamable_subset()... ");
-       if(encoder->get_streamable_subset() != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_mid_side_stereo()... ");
-       if(encoder->get_do_mid_side_stereo() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_loose_mid_side_stereo()... ");
-       if(encoder->get_loose_mid_side_stereo() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_channels()... ");
-       if(encoder->get_channels() != streaminfo_.data.stream_info.channels) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, encoder->get_channels());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_bits_per_sample()... ");
-       if(encoder->get_bits_per_sample() != streaminfo_.data.stream_info.bits_per_sample) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, encoder->get_bits_per_sample());
-               return false;
-       }
-       printf("OK\n");
+       init_metadata_blocks_();
 
-       printf("testing get_sample_rate()... ");
-       if(encoder->get_sample_rate() != streaminfo_.data.stream_info.sample_rate) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, encoder->get_sample_rate());
+       if(!test_stream_encoder(LAYER_STREAM))
                return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_blocksize()... ");
-       if(encoder->get_blocksize() != streaminfo_.data.stream_info.min_blocksize) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, encoder->get_blocksize());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_max_lpc_order()... ");
-       if(encoder->get_max_lpc_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_lpc_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_qlp_coeff_precision()... ");
-       (void)encoder->get_qlp_coeff_precision();
-       /* we asked the encoder to auto select this so we accept anything */
-       printf("OK\n");
-
-       printf("testing get_do_qlp_coeff_prec_search()... ");
-       if(encoder->get_do_qlp_coeff_prec_search() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_escape_coding()... ");
-       if(encoder->get_do_escape_coding() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_exhaustive_model_search()... ");
-       if(encoder->get_do_exhaustive_model_search() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_min_residual_partition_order()... ");
-       if(encoder->get_min_residual_partition_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_min_residual_partition_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_max_residual_partition_order()... ");
-       if(encoder->get_max_residual_partition_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_residual_partition_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_rice_parameter_search_dist()... ");
-       if(encoder->get_rice_parameter_search_dist() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_rice_parameter_search_dist());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_total_samples_estimate()... ");
-       if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
-               printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
-               return false;
-       }
-       printf("OK\n");
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       printf("testing process()... ");
-       if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_interleaved()... ");
-       if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       encoder->finish();
-       printf("OK\n");
-
-       printf("freeing encoder instance... ");
-       delete encoder;
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-class FileEncoder : public FLAC::Encoder::File {
-public:
-       FileEncoder(): FLAC::Encoder::File() { }
-       ~FileEncoder() { }
-
-       // from FLAC::Encoder::File
-       void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate);
-
-       bool die(const char *msg = 0) const;
-};
-
-void FileEncoder::progress_callback(FLAC__uint64, FLAC__uint64, unsigned, unsigned)
-{
-}
-
-bool FileEncoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::FLAC__FileEncoderState)state), state.as_cstring());
-       if(state == ::FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR) {
-               FLAC::Encoder::SeekableStream::State state_ = get_seekable_stream_encoder_state();
-               printf("      seekable stream encoder state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamEncoderState)state_), state_.as_cstring());
-               if(state_ == ::FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) {
-                       FLAC::Encoder::Stream::State state__ = get_stream_encoder_state();
-                       printf("      stream encoder state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state__), state__.as_cstring());
-                       if(state__ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                               FLAC::Decoder::Stream::State dstate = get_verify_decoder_state();
-                               printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-                       }
-               }
-       }
-
-       return false;
-}
-
-static bool test_file_encoder()
-{
-       FileEncoder *encoder;
-       FLAC__int32 samples[1024];
-       FLAC__int32 *samples_array[1] = { samples };
-       unsigned i;
-
-       printf("\n+++ libFLAC++ unit test: FLAC::Encoder::File\n\n");
-
-       printf("allocating encoder instance... ");
-       encoder = new FileEncoder();
-       if(0 == encoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!encoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_verify()... ");
-       if(!encoder->set_verify(true))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_streamable_subset()... ");
-       if(!encoder->set_streamable_subset(true))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_mid_side_stereo()... ");
-       if(!encoder->set_do_mid_side_stereo(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_loose_mid_side_stereo()... ");
-       if(!encoder->set_loose_mid_side_stereo(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_channels()... ");
-       if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_bits_per_sample()... ");
-       if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_sample_rate()... ");
-       if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_blocksize()... ");
-       if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_max_lpc_order()... ");
-       if(!encoder->set_max_lpc_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_qlp_coeff_precision()... ");
-       if(!encoder->set_qlp_coeff_precision(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_qlp_coeff_prec_search()... ");
-       if(!encoder->set_do_qlp_coeff_prec_search(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_escape_coding()... ");
-       if(!encoder->set_do_escape_coding(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_exhaustive_model_search()... ");
-       if(!encoder->set_do_exhaustive_model_search(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_min_residual_partition_order()... ");
-       if(!encoder->set_min_residual_partition_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_max_residual_partition_order()... ");
-       if(!encoder->set_max_residual_partition_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_rice_parameter_search_dist()... ");
-       if(!encoder->set_rice_parameter_search_dist(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_total_samples_estimate()... ");
-       if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_metadata()... ");
-       if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_filename()... ");
-       if(!encoder->set_filename(flacfilename_))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(encoder->init() != ::FLAC__FILE_ENCODER_OK)
-               return encoder->die();
-       printf("OK\n");
-
-       printf("testing get_state()... ");
-       FLAC::Encoder::File::State state = encoder->get_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__FileEncoderState)state), state.as_cstring());
-
-       printf("testing get_seekable_stream_encoder_state()... ");
-       FLAC::Encoder::SeekableStream::State state_ = encoder->get_seekable_stream_encoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamEncoderState)state_), state_.as_cstring());
-
-       printf("testing get_stream_encoder_state()... ");
-       FLAC::Encoder::Stream::State state__ = encoder->get_stream_encoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state__), state__.as_cstring());
-
-       printf("testing get_verify_decoder_state()... ");
-       FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-
-       {
-               FLAC__uint64 absolute_sample;
-               unsigned frame_number;
-               unsigned channel;
-               unsigned sample;
-               FLAC__int32 expected;
-               FLAC__int32 got;
-
-               printf("testing get_verify_decoder_error_stats()... ");
-               encoder->get_verify_decoder_error_stats(&absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               printf("OK\n");
-       }
-
-       printf("testing get_verify()... ");
-       if(encoder->get_verify() != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_streamable_subset()... ");
-       if(encoder->get_streamable_subset() != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_mid_side_stereo()... ");
-       if(encoder->get_do_mid_side_stereo() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_loose_mid_side_stereo()... ");
-       if(encoder->get_loose_mid_side_stereo() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_channels()... ");
-       if(encoder->get_channels() != streaminfo_.data.stream_info.channels) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, encoder->get_channels());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_bits_per_sample()... ");
-       if(encoder->get_bits_per_sample() != streaminfo_.data.stream_info.bits_per_sample) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, encoder->get_bits_per_sample());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_sample_rate()... ");
-       if(encoder->get_sample_rate() != streaminfo_.data.stream_info.sample_rate) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, encoder->get_sample_rate());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_blocksize()... ");
-       if(encoder->get_blocksize() != streaminfo_.data.stream_info.min_blocksize) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, encoder->get_blocksize());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_max_lpc_order()... ");
-       if(encoder->get_max_lpc_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_lpc_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_qlp_coeff_precision()... ");
-       (void)encoder->get_qlp_coeff_precision();
-       /* we asked the encoder to auto select this so we accept anything */
-       printf("OK\n");
-
-       printf("testing get_do_qlp_coeff_prec_search()... ");
-       if(encoder->get_do_qlp_coeff_prec_search() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_escape_coding()... ");
-       if(encoder->get_do_escape_coding() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_exhaustive_model_search()... ");
-       if(encoder->get_do_exhaustive_model_search() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_min_residual_partition_order()... ");
-       if(encoder->get_min_residual_partition_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_min_residual_partition_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_max_residual_partition_order()... ");
-       if(encoder->get_max_residual_partition_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_residual_partition_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_rice_parameter_search_dist()... ");
-       if(encoder->get_rice_parameter_search_dist() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_rice_parameter_search_dist());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_total_samples_estimate()... ");
-       if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
-               printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
-               return false;
-       }
-       printf("OK\n");
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       printf("testing process()... ");
-       if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_interleaved()... ");
-       if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       encoder->finish();
-       printf("OK\n");
-
-       printf("freeing encoder instance... ");
-       delete encoder;
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-bool test_encoders()
-{
-       init_metadata_blocks_();
 
-       if(!test_stream_encoder())
+       if(!test_stream_encoder(LAYER_SEEKABLE_STREAM))
                return false;
 
-       if(!test_seekable_stream_encoder())
+       if(!test_stream_encoder(LAYER_FILE))
                return false;
 
-       if(!test_file_encoder())
+       if(!test_stream_encoder(LAYER_FILENAME))
                return false;
 
        free_metadata_blocks_();
diff --git a/src/test_libFLAC++/file_utils.h b/src/test_libFLAC++/file_utils.h
deleted file mode 100644 (file)
index 4b69568..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* test_libFLAC - Unit tester for libFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef FLAC__TEST_LIBFLAC_FILE_UTILS_H
-#define FLAC__TEST_LIBFLAC_FILE_UTILS_H
-
-/* needed because of off_t */
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FLAC/format.h"
-#include <sys/types.h> /* for off_t */
-
-FLAC__bool file_utils__generate_flacfile(const char *output_filename, off_t *output_filesize, unsigned length, const FLAC__StreamMetadata *streaminfo, FLAC__StreamMetadata **metadata, unsigned num_metadata);
-
-#endif
index ada4f9e..f1c34ab 100644 (file)
 #include <unistd.h> /* for chown(), unlink() */
 #endif
 #include <sys/stat.h> /* for stat(), maybe chmod() */
-extern "C" {
-#include "file_utils.h"
-}
 #include "FLAC/assert.h"
 #include "FLAC++/decoder.h"
 #include "FLAC++/metadata.h"
 #include "share/grabbag.h"
+extern "C" {
+#include "test_libs_common/file_utils_flac.h"
+}
 
 /******************************************************************************
        The general strategy of these tests (for interface levels 1 and 2) is
@@ -568,13 +568,12 @@ static bool test_file_(const char *filename, bool ignore_metadata)
                return die_("couldn't allocate decoder instance");
 
        decoder.set_md5_checking(true);
-       decoder.set_filename(filename);
        decoder.set_metadata_respond_all();
-       if(decoder.init() != ::FLAC__FILE_DECODER_OK) {
+       if(decoder.init(filename) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK) {
                decoder.finish();
                return die_("initializing decoder\n");
        }
-       if(!decoder.process_until_end_of_file()) {
+       if(!decoder.process_until_end_of_stream()) {
                decoder.finish();
                return die_("decoding file\n");
        }
diff --git a/src/test_libFLAC++/metadata_utils.c b/src/test_libFLAC++/metadata_utils.c
deleted file mode 100644 (file)
index c866982..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-/* test_libFLAC - Unit tester for libFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * These are not tests, just utility functions used by the metadata tests
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "metadata_utils.h"
-#include "FLAC/metadata.h"
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for memcmp() */
-
-FLAC__bool mutils__compare_block_data_streaminfo(const FLAC__StreamMetadata_StreamInfo *block, const FLAC__StreamMetadata_StreamInfo *blockcopy)
-{
-       if(blockcopy->min_blocksize != block->min_blocksize) {
-               printf("FAILED, min_blocksize mismatch, expected %u, got %u\n", block->min_blocksize, blockcopy->min_blocksize);
-               return false;
-       }
-       if(blockcopy->max_blocksize != block->max_blocksize) {
-               printf("FAILED, max_blocksize mismatch, expected %u, got %u\n", block->max_blocksize, blockcopy->max_blocksize);
-               return false;
-       }
-       if(blockcopy->min_framesize != block->min_framesize) {
-               printf("FAILED, min_framesize mismatch, expected %u, got %u\n", block->min_framesize, blockcopy->min_framesize);
-               return false;
-       }
-       if(blockcopy->max_framesize != block->max_framesize) {
-               printf("FAILED, max_framesize mismatch, expected %u, got %u\n", block->max_framesize, blockcopy->max_framesize);
-               return false;
-       }
-       if(blockcopy->sample_rate != block->sample_rate) {
-               printf("FAILED, sample_rate mismatch, expected %u, got %u\n", block->sample_rate, blockcopy->sample_rate);
-               return false;
-       }
-       if(blockcopy->channels != block->channels) {
-               printf("FAILED, channels mismatch, expected %u, got %u\n", block->channels, blockcopy->channels);
-               return false;
-       }
-       if(blockcopy->bits_per_sample != block->bits_per_sample) {
-               printf("FAILED, bits_per_sample mismatch, expected %u, got %u\n", block->bits_per_sample, blockcopy->bits_per_sample);
-               return false;
-       }
-       if(blockcopy->total_samples != block->total_samples) {
-               printf("FAILED, total_samples mismatch, expected %llu, got %llu\n", block->total_samples, blockcopy->total_samples);
-               return false;
-       }
-       if(0 != memcmp(blockcopy->md5sum, block->md5sum, sizeof(block->md5sum))) {
-               printf("FAILED, md5sum mismatch, expected %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X, got %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
-                       (unsigned)block->md5sum[0],
-                       (unsigned)block->md5sum[1],
-                       (unsigned)block->md5sum[2],
-                       (unsigned)block->md5sum[3],
-                       (unsigned)block->md5sum[4],
-                       (unsigned)block->md5sum[5],
-                       (unsigned)block->md5sum[6],
-                       (unsigned)block->md5sum[7],
-                       (unsigned)block->md5sum[8],
-                       (unsigned)block->md5sum[9],
-                       (unsigned)block->md5sum[10],
-                       (unsigned)block->md5sum[11],
-                       (unsigned)block->md5sum[12],
-                       (unsigned)block->md5sum[13],
-                       (unsigned)block->md5sum[14],
-                       (unsigned)block->md5sum[15],
-                       (unsigned)blockcopy->md5sum[0],
-                       (unsigned)blockcopy->md5sum[1],
-                       (unsigned)blockcopy->md5sum[2],
-                       (unsigned)blockcopy->md5sum[3],
-                       (unsigned)blockcopy->md5sum[4],
-                       (unsigned)blockcopy->md5sum[5],
-                       (unsigned)blockcopy->md5sum[6],
-                       (unsigned)blockcopy->md5sum[7],
-                       (unsigned)blockcopy->md5sum[8],
-                       (unsigned)blockcopy->md5sum[9],
-                       (unsigned)blockcopy->md5sum[10],
-                       (unsigned)blockcopy->md5sum[11],
-                       (unsigned)blockcopy->md5sum[12],
-                       (unsigned)blockcopy->md5sum[13],
-                       (unsigned)blockcopy->md5sum[14],
-                       (unsigned)blockcopy->md5sum[15]
-               );
-               return false;
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_padding(const FLAC__StreamMetadata_Padding *block, const FLAC__StreamMetadata_Padding *blockcopy, unsigned block_length)
-{
-       /* we don't compare the padding guts */
-       (void)block, (void)blockcopy, (void)block_length;
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_application(const FLAC__StreamMetadata_Application *block, const FLAC__StreamMetadata_Application *blockcopy, unsigned block_length)
-{
-       if(block_length < sizeof(block->id)) {
-               printf("FAILED, bad block length = %u\n", block_length);
-               return false;
-       }
-       if(0 != memcmp(blockcopy->id, block->id, sizeof(block->id))) {
-               printf("FAILED, id mismatch, expected %02X%02X%02X%02X, got %02X%02X%02X%02X\n",
-                       (unsigned)block->id[0],
-                       (unsigned)block->id[1],
-                       (unsigned)block->id[2],
-                       (unsigned)block->id[3],
-                       (unsigned)blockcopy->id[0],
-                       (unsigned)blockcopy->id[1],
-                       (unsigned)blockcopy->id[2],
-                       (unsigned)blockcopy->id[3]
-               );
-               return false;
-       }
-       if(0 == block->data || 0 == blockcopy->data) {
-               if(block->data != blockcopy->data) {
-                       printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
-                       return false;
-               }
-               else if(block_length - sizeof(block->id) > 0) {
-                       printf("FAILED, data pointer is null but block length is not 0\n");
-                       return false;
-               }
-       }
-       else {
-               if(block_length - sizeof(block->id) == 0) {
-                       printf("FAILED, data pointer is not null but block length is 0\n");
-                       return false;
-               }
-               else if(0 != memcmp(blockcopy->data, block->data, block_length - sizeof(block->id))) {
-                       printf("FAILED, data mismatch\n");
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_seektable(const FLAC__StreamMetadata_SeekTable *block, const FLAC__StreamMetadata_SeekTable *blockcopy)
-{
-       unsigned i;
-       if(blockcopy->num_points != block->num_points) {
-               printf("FAILED, num_points mismatch, expected %u, got %u\n", block->num_points, blockcopy->num_points);
-               return false;
-       }
-       for(i = 0; i < block->num_points; i++) {
-               if(blockcopy->points[i].sample_number != block->points[i].sample_number) {
-                       printf("FAILED, points[%u].sample_number mismatch, expected %llu, got %llu\n", i, block->points[i].sample_number, blockcopy->points[i].sample_number);
-                       return false;
-               }
-               if(blockcopy->points[i].stream_offset != block->points[i].stream_offset) {
-                       printf("FAILED, points[%u].stream_offset mismatch, expected %llu, got %llu\n", i, block->points[i].stream_offset, blockcopy->points[i].stream_offset);
-                       return false;
-               }
-               if(blockcopy->points[i].frame_samples != block->points[i].frame_samples) {
-                       printf("FAILED, points[%u].frame_samples mismatch, expected %u, got %u\n", i, block->points[i].frame_samples, blockcopy->points[i].frame_samples);
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_vorbiscomment(const FLAC__StreamMetadata_VorbisComment *block, const FLAC__StreamMetadata_VorbisComment *blockcopy)
-{
-       unsigned i;
-       if(blockcopy->vendor_string.length != block->vendor_string.length) {
-               printf("FAILED, vendor_string.length mismatch, expected %u, got %u\n", block->vendor_string.length, blockcopy->vendor_string.length);
-               return false;
-       }
-       if(0 == block->vendor_string.entry || 0 == blockcopy->vendor_string.entry) {
-               if(block->vendor_string.entry != blockcopy->vendor_string.entry) {
-                       printf("FAILED, vendor_string.entry mismatch\n");
-                       return false;
-               }
-       }
-       else if(0 != memcmp(blockcopy->vendor_string.entry, block->vendor_string.entry, block->vendor_string.length)) {
-               printf("FAILED, vendor_string.entry mismatch\n");
-               return false;
-       }
-       if(blockcopy->num_comments != block->num_comments) {
-               printf("FAILED, num_comments mismatch, expected %u, got %u\n", block->num_comments, blockcopy->num_comments);
-               return false;
-       }
-       for(i = 0; i < block->num_comments; i++) {
-               if(blockcopy->comments[i].length != block->comments[i].length) {
-                       printf("FAILED, comments[%u].length mismatch, expected %u, got %u\n", i, block->comments[i].length, blockcopy->comments[i].length);
-                       return false;
-               }
-               if(0 == block->comments[i].entry || 0 == blockcopy->comments[i].entry) {
-                       if(block->comments[i].entry != blockcopy->comments[i].entry) {
-                               printf("FAILED, comments[%u].entry mismatch\n", i);
-                               return false;
-                       }
-               }
-               else {
-                       if(0 != memcmp(blockcopy->comments[i].entry, block->comments[i].entry, block->comments[i].length)) {
-                               printf("FAILED, comments[%u].entry mismatch\n", i);
-                               return false;
-                       }
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_cuesheet(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy)
-{
-       unsigned i, j;
-
-       if(0 != strcmp(blockcopy->media_catalog_number, block->media_catalog_number)) {
-               printf("FAILED, media_catalog_number mismatch, expected %s, got %s\n", block->media_catalog_number, blockcopy->media_catalog_number);
-               return false;
-       }
-       if(blockcopy->lead_in != block->lead_in) {
-               printf("FAILED, lead_in mismatch, expected %llu, got %llu\n", block->lead_in, blockcopy->lead_in);
-               return false;
-       }
-       if(blockcopy->is_cd != block->is_cd) {
-               printf("FAILED, is_cd mismatch, expected %u, got %u\n", (unsigned)block->is_cd, (unsigned)blockcopy->is_cd);
-               return false;
-       }
-       if(blockcopy->num_tracks != block->num_tracks) {
-               printf("FAILED, num_tracks mismatch, expected %u, got %u\n", block->num_tracks, blockcopy->num_tracks);
-               return false;
-       }
-       for(i = 0; i < block->num_tracks; i++) {
-               if(blockcopy->tracks[i].offset != block->tracks[i].offset) {
-                       printf("FAILED, tracks[%u].offset mismatch, expected %llu, got %llu\n", i, block->tracks[i].offset, blockcopy->tracks[i].offset);
-                       return false;
-               }
-               if(blockcopy->tracks[i].number != block->tracks[i].number) {
-                       printf("FAILED, tracks[%u].number mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].number, (unsigned)blockcopy->tracks[i].number);
-                       return false;
-               }
-               if(blockcopy->tracks[i].num_indices != block->tracks[i].num_indices) {
-                       printf("FAILED, tracks[%u].num_indices mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].num_indices, (unsigned)blockcopy->tracks[i].num_indices);
-                       return false;
-               }
-               /* num_indices == 0 means lead-out track so only the track offset and number are valid */
-               if(block->tracks[i].num_indices > 0) {
-                       if(0 != strcmp(blockcopy->tracks[i].isrc, block->tracks[i].isrc)) {
-                               printf("FAILED, tracks[%u].isrc mismatch, expected %s, got %s\n", i, block->tracks[i].isrc, blockcopy->tracks[i].isrc);
-                               return false;
-                       }
-                       if(blockcopy->tracks[i].type != block->tracks[i].type) {
-                               printf("FAILED, tracks[%u].type mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].type, (unsigned)blockcopy->tracks[i].type);
-                               return false;
-                       }
-                       if(blockcopy->tracks[i].pre_emphasis != block->tracks[i].pre_emphasis) {
-                               printf("FAILED, tracks[%u].pre_emphasis mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].pre_emphasis, (unsigned)blockcopy->tracks[i].pre_emphasis);
-                               return false;
-                       }
-                       if(0 == block->tracks[i].indices || 0 == blockcopy->tracks[i].indices) {
-                               if(block->tracks[i].indices != blockcopy->tracks[i].indices) {
-                                       printf("FAILED, tracks[%u].indices mismatch\n", i);
-                                       return false;
-                               }
-                       }
-                       else {
-                               for(j = 0; j < block->tracks[i].num_indices; j++) {
-                                       if(blockcopy->tracks[i].indices[j].offset != block->tracks[i].indices[j].offset) {
-                                               printf("FAILED, tracks[%u].indices[%u].offset mismatch, expected %llu, got %llu\n", i, j, block->tracks[i].indices[j].offset, blockcopy->tracks[i].indices[j].offset);
-                                               return false;
-                                       }
-                                       if(blockcopy->tracks[i].indices[j].number != block->tracks[i].indices[j].number) {
-                                               printf("FAILED, tracks[%u].indices[%u].number mismatch, expected %u, got %u\n", i, j, (unsigned)block->tracks[i].indices[j].number, (unsigned)blockcopy->tracks[i].indices[j].number);
-                                               return false;
-                                       }
-                               }
-                       }
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length)
-{
-       if(0 == block->data || 0 == blockcopy->data) {
-               if(block->data != blockcopy->data) {
-                       printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
-                       return false;
-               }
-               else if(block_length > 0) {
-                       printf("FAILED, data pointer is null but block length is not 0\n");
-                       return false;
-               }
-       }
-       else {
-               if(block_length == 0) {
-                       printf("FAILED, data pointer is not null but block length is 0\n");
-                       return false;
-               }
-               else if(0 != memcmp(blockcopy->data, block->data, block_length)) {
-                       printf("FAILED, data mismatch\n");
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy)
-{
-       if(blockcopy->type != block->type) {
-               printf("FAILED, type mismatch, expected %s, got %s\n", FLAC__MetadataTypeString[block->type], FLAC__MetadataTypeString[blockcopy->type]);
-               return false;
-       }
-       if(blockcopy->is_last != block->is_last) {
-               printf("FAILED, is_last mismatch, expected %u, got %u\n", (unsigned)block->is_last, (unsigned)blockcopy->is_last);
-               return false;
-       }
-       if(blockcopy->length != block->length) {
-               printf("FAILED, length mismatch, expected %u, got %u\n", block->length, blockcopy->length);
-               return false;
-       }
-       switch(block->type) {
-               case FLAC__METADATA_TYPE_STREAMINFO:
-                       return mutils__compare_block_data_streaminfo(&block->data.stream_info, &blockcopy->data.stream_info);
-               case FLAC__METADATA_TYPE_PADDING:
-                       return mutils__compare_block_data_padding(&block->data.padding, &blockcopy->data.padding, block->length);
-               case FLAC__METADATA_TYPE_APPLICATION:
-                       return mutils__compare_block_data_application(&block->data.application, &blockcopy->data.application, block->length);
-               case FLAC__METADATA_TYPE_SEEKTABLE:
-                       return mutils__compare_block_data_seektable(&block->data.seek_table, &blockcopy->data.seek_table);
-               case FLAC__METADATA_TYPE_VORBIS_COMMENT:
-                       return mutils__compare_block_data_vorbiscomment(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
-               case FLAC__METADATA_TYPE_CUESHEET:
-                       return mutils__compare_block_data_cuesheet(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
-               default:
-                       return mutils__compare_block_data_unknown(&block->data.unknown, &blockcopy->data.unknown, block->length);
-       }
-}
-static void *malloc_or_die_(size_t size)
-{
-       void *x = malloc(size);
-       if(0 == x) {
-               fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
-               exit(1);
-       }
-       return x;
-}
-
-static void *calloc_or_die_(size_t n, size_t size)
-{
-       void *x = calloc(n, size);
-       if(0 == x) {
-               fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)n * (unsigned)size);
-               exit(1);
-       }
-       return x;
-}
-
-void mutils__init_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-)
-{
-       /*
-               most of the actual numbers and data in the blocks don't matter,
-               we just want to make sure the decoder parses them correctly
-
-               remember, the metadata interface gets tested after the decoders,
-               so we do all the metadata manipulation here without it.
-       */
-
-       /* min/max_framesize and md5sum don't get written at first, so we have to leave them 0 */
-       streaminfo->is_last = false;
-       streaminfo->type = FLAC__METADATA_TYPE_STREAMINFO;
-       streaminfo->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
-       streaminfo->data.stream_info.min_blocksize = 576;
-       streaminfo->data.stream_info.max_blocksize = 576;
-       streaminfo->data.stream_info.min_framesize = 0;
-       streaminfo->data.stream_info.max_framesize = 0;
-       streaminfo->data.stream_info.sample_rate = 44100;
-       streaminfo->data.stream_info.channels = 1;
-       streaminfo->data.stream_info.bits_per_sample = 8;
-       streaminfo->data.stream_info.total_samples = 0;
-       memset(streaminfo->data.stream_info.md5sum, 0, 16);
-
-       padding->is_last = false;
-       padding->type = FLAC__METADATA_TYPE_PADDING;
-       padding->length = 1234;
-
-       seektable->is_last = false;
-       seektable->type = FLAC__METADATA_TYPE_SEEKTABLE;
-       seektable->data.seek_table.num_points = 2;
-       seektable->length = seektable->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
-       seektable->data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)malloc_or_die_(seektable->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint));
-       seektable->data.seek_table.points[0].sample_number = 0;
-       seektable->data.seek_table.points[0].stream_offset = 0;
-       seektable->data.seek_table.points[0].frame_samples = streaminfo->data.stream_info.min_blocksize;
-       seektable->data.seek_table.points[1].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
-       seektable->data.seek_table.points[1].stream_offset = 1000;
-       seektable->data.seek_table.points[1].frame_samples = streaminfo->data.stream_info.min_blocksize;
-
-       application1->is_last = false;
-       application1->type = FLAC__METADATA_TYPE_APPLICATION;
-       application1->length = 8;
-       memcpy(application1->data.application.id, "\xfe\xdc\xba\x98", 4);
-       application1->data.application.data = (FLAC__byte*)malloc_or_die_(4);
-       memcpy(application1->data.application.data, "\xf0\xe1\xd2\xc3", 4);
-
-       application2->is_last = false;
-       application2->type = FLAC__METADATA_TYPE_APPLICATION;
-       application2->length = 4;
-       memcpy(application2->data.application.id, "\x76\x54\x32\x10", 4);
-       application2->data.application.data = 0;
-
-       {
-               const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
-               vorbiscomment->is_last = false;
-               vorbiscomment->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
-               vorbiscomment->length = (4 + vendor_string_length) + 4 + (4 + 5) + (4 + 0);
-               vorbiscomment->data.vorbis_comment.vendor_string.length = vendor_string_length;
-               vorbiscomment->data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
-               memcpy(vorbiscomment->data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
-               vorbiscomment->data.vorbis_comment.num_comments = 2;
-               vorbiscomment->data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc_or_die_(vorbiscomment->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
-               vorbiscomment->data.vorbis_comment.comments[0].length = 5;
-               vorbiscomment->data.vorbis_comment.comments[0].entry = (FLAC__byte*)malloc_or_die_(5+1);
-               memcpy(vorbiscomment->data.vorbis_comment.comments[0].entry, "ab=cd", 5+1);
-               vorbiscomment->data.vorbis_comment.comments[1].length = 0;
-               vorbiscomment->data.vorbis_comment.comments[1].entry = 0;
-       }
-
-       cuesheet->is_last = false;
-       cuesheet->type = FLAC__METADATA_TYPE_CUESHEET;
-       cuesheet->length =
-               /* cuesheet guts */
-               (
-                       FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
-               ) / 8 +
-               /* 2 tracks */
-               3 * (
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
-               ) / 8 +
-               /* 3 index points */
-               3 * (
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
-               ) / 8
-       ;
-       memset(cuesheet->data.cue_sheet.media_catalog_number, 0, sizeof(cuesheet->data.cue_sheet.media_catalog_number));
-       cuesheet->data.cue_sheet.media_catalog_number[0] = 'j';
-       cuesheet->data.cue_sheet.media_catalog_number[1] = 'C';
-       cuesheet->data.cue_sheet.lead_in = 2 * 44100;
-       cuesheet->data.cue_sheet.is_cd = true;
-       cuesheet->data.cue_sheet.num_tracks = 3;
-       cuesheet->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc_or_die_(cuesheet->data.cue_sheet.num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));
-       cuesheet->data.cue_sheet.tracks[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[0].number = 1;
-       memcpy(cuesheet->data.cue_sheet.tracks[0].isrc, "ACBDE1234567", sizeof(cuesheet->data.cue_sheet.tracks[0].isrc));
-       cuesheet->data.cue_sheet.tracks[0].type = 0;
-       cuesheet->data.cue_sheet.tracks[0].pre_emphasis = 1;
-       cuesheet->data.cue_sheet.tracks[0].num_indices = 2;
-       cuesheet->data.cue_sheet.tracks[0].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet->data.cue_sheet.tracks[0].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
-       cuesheet->data.cue_sheet.tracks[0].indices[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[0].indices[0].number = 0;
-       cuesheet->data.cue_sheet.tracks[0].indices[1].offset = 123 * 588;
-       cuesheet->data.cue_sheet.tracks[0].indices[1].number = 1;
-       cuesheet->data.cue_sheet.tracks[1].offset = 1234 * 588;
-       cuesheet->data.cue_sheet.tracks[1].number = 2;
-       memcpy(cuesheet->data.cue_sheet.tracks[1].isrc, "ACBDE7654321", sizeof(cuesheet->data.cue_sheet.tracks[1].isrc));
-       cuesheet->data.cue_sheet.tracks[1].type = 1;
-       cuesheet->data.cue_sheet.tracks[1].pre_emphasis = 0;
-       cuesheet->data.cue_sheet.tracks[1].num_indices = 1;
-       cuesheet->data.cue_sheet.tracks[1].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet->data.cue_sheet.tracks[1].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
-       cuesheet->data.cue_sheet.tracks[1].indices[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[1].indices[0].number = 1;
-       cuesheet->data.cue_sheet.tracks[2].offset = 12345 * 588;
-       cuesheet->data.cue_sheet.tracks[2].number = 170;
-       cuesheet->data.cue_sheet.tracks[2].num_indices = 0;
-
-       unknown->is_last = true;
-       unknown->type = 127;
-       unknown->length = 8;
-       unknown->data.unknown.data = (FLAC__byte*)malloc_or_die_(unknown->length);
-       memcpy(unknown->data.unknown.data, "\xfe\xdc\xba\x98\xf0\xe1\xd2\xc3", unknown->length);
-}
-
-void mutils__free_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-)
-{
-       (void)streaminfo, (void)padding, (void)application2;
-       free(seektable->data.seek_table.points);
-       free(application1->data.application.data);
-       free(vorbiscomment->data.vorbis_comment.vendor_string.entry);
-       free(vorbiscomment->data.vorbis_comment.comments[0].entry);
-       free(vorbiscomment->data.vorbis_comment.comments);
-       free(cuesheet->data.cue_sheet.tracks[0].indices);
-       free(cuesheet->data.cue_sheet.tracks[1].indices);
-       free(cuesheet->data.cue_sheet.tracks);
-       free(unknown->data.unknown.data);
-}
diff --git a/src/test_libFLAC++/metadata_utils.h b/src/test_libFLAC++/metadata_utils.h
deleted file mode 100644 (file)
index 3d7af19..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* test_libFLAC - Unit tester for libFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef FLAC__TEST_LIBFLAC_METADATA_H
-#define FLAC__TEST_LIBFLAC_METADATA_H
-
-/*
- * These are not tests, just utility functions used by the metadata tests
- */
-
-#include "FLAC/format.h"
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for memcmp() */
-
-FLAC__bool mutils__compare_block_data_streaminfo(const FLAC__StreamMetadata_StreamInfo *block, const FLAC__StreamMetadata_StreamInfo *blockcopy);
-
-FLAC__bool mutils__compare_block_data_padding(const FLAC__StreamMetadata_Padding *block, const FLAC__StreamMetadata_Padding *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block_data_application(const FLAC__StreamMetadata_Application *block, const FLAC__StreamMetadata_Application *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block_data_seektable(const FLAC__StreamMetadata_SeekTable *block, const FLAC__StreamMetadata_SeekTable *blockcopy);
-
-FLAC__bool mutils__compare_block_data_vorbiscomment(const FLAC__StreamMetadata_VorbisComment *block, const FLAC__StreamMetadata_VorbisComment *blockcopy);
-
-FLAC__bool mutils__compare_block_data_cuesheet(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy);
-
-FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy);
-
-void mutils__init_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-);
-
-void mutils__free_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-);
-
-#endif
index 0702a7d..ab90c4e 100644 (file)
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
-# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\libFLAC++_static.lib ..\..\obj\release\lib\libFLAC_static.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\test_libs_common_static.lib ..\..\obj\release\lib\libFLAC++_static.lib ..\..\obj\release\lib\libFLAC_static.lib /nologo /subsystem:console /machine:I386\r
 \r
 !ELSEIF  "$(CFG)" == "test_libFLAC++ - Win32 Debug"\r
 \r
@@ -76,7 +76,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\libFLAC++_static.lib ..\..\obj\debug\lib\libFLAC_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\test_libs_common_static.lib ..\..\obj\debug\lib\libFLAC++_static.lib ..\..\obj\debug\lib\libFLAC_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
 \r
 !ENDIF \r
 \r
@@ -97,10 +97,6 @@ SOURCE=.\encoders.cpp
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\file_utils.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\main.cpp\r
 # End Source File\r
 # Begin Source File\r
@@ -115,10 +111,6 @@ SOURCE=.\metadata_manip.cpp
 \r
 SOURCE=.\metadata_object.cpp\r
 # End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\metadata_utils.c\r
-# End Source File\r
 # End Group\r
 # Begin Group "Header Files"\r
 \r
@@ -133,16 +125,8 @@ SOURCE=.\encoders.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\file_utils.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\metadata.h\r
 # End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\metadata_utils.h\r
-# End Source File\r
 # End Group\r
 # Begin Source File\r
 \r
index 1e6449c..960acbd 100644 (file)
@@ -25,23 +25,20 @@ noinst_PROGRAMS = test_libFLAC
 test_libFLAC_LDADD = \
        $(top_builddir)/src/share/grabbag/libgrabbag.la \
        $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+       $(top_builddir)/src/test_libs_common/libtest_libs_common.la \
        $(top_builddir)/src/libFLAC/libFLAC.la \
        -lm
 test_libFLAC_SOURCES = \
        bitbuffer.c \
        decoders.c \
        encoders.c \
-       file_utils.c \
        format.c \
        main.c \
        metadata.c \
        metadata_manip.c \
        metadata_object.c \
-       metadata_utils.c \
        bitbuffer.h \
        decoders.h \
        encoders.h \
-       file_utils.h \
        format.h \
-       metadata.h \
-       metadata_utils.h
+       metadata.h
index 738d0bb..ed2b797 100644 (file)
@@ -27,22 +27,20 @@ PROGRAM_NAME = test_libFLAC
 INCLUDES = -I../libFLAC/include -I$(topdir)/include
 
 ifeq ($(DARWIN_BUILD),yes)
-EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libreplaygain_analysis.a $(libdir)/libFLAC.a -lm
+EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libreplaygain_analysis.a $(libdir)/libtest_libs_common.a $(libdir)/libFLAC.a -lm
 else
-LIBS = -lgrabbag -lreplaygain_analysis -lFLAC -lm
+LIBS = -lgrabbag -lreplaygain_analysis -ltest_libs_common -lOggFLAC -lFLAC -L$(OGG_LIB_DIR) -logg -lm
 endif
 
 SRCS_C = \
        bitbuffer.c \
        decoders.c \
        encoders.c \
-       file_utils.c \
        format.c \
        main.c \
        metadata.c \
        metadata_manip.c \
-       metadata_object.c \
-       metadata_utils.c
+       metadata_object.c
 
 include $(topdir)/build/exe.mk
 
index f208a5b..1ac22d4 100644 (file)
 #define ftello ftell
 #endif
 #include "decoders.h"
-#include "file_utils.h"
-#include "metadata_utils.h"
 #include "FLAC/assert.h"
-#include "FLAC/file_decoder.h"
-#include "FLAC/seekable_stream_decoder.h"
 #include "FLAC/stream_decoder.h"
 #include "share/grabbag.h"
+#include "test_libs_common/file_utils_flac.h"
+#include "test_libs_common/metadata_utils.h"
+
+typedef enum {
+       LAYER_STREAM = 0, /* FLAC__stream_decoder_init_stream() without seeking */
+       LAYER_SEEKABLE_STREAM, /* FLAC__stream_decoder_init_stream() with seeking */
+       LAYER_FILE, /* FLAC__stream_decoder_init_FILE() */
+       LAYER_FILENAME /* FLAC__stream_decoder_init_file() */
+} Layer;
+
+static const char * const LayerString[] = {
+       "Stream",
+       "Seekable Stream",
+       "FILE*",
+       "Filename"
+};
 
 typedef struct {
+       Layer layer;
        FILE *file;
        unsigned current_metadata_number;
        FLAC__bool ignore_errors;
        FLAC__bool error_occurred;
-} stream_decoder_client_data_struct;
-
-typedef stream_decoder_client_data_struct seekable_stream_decoder_client_data_struct;
-typedef stream_decoder_client_data_struct file_decoder_client_data_struct;
+} StreamDecoderClientData;
 
 static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
 static FLAC__StreamMetadata *expected_metadata_sequence_[8];
@@ -74,46 +84,6 @@ static FLAC__bool die_s_(const char *msg, const FLAC__StreamDecoder *decoder)
        return false;
 }
 
-static FLAC__bool die_ss_(const char *msg, const FLAC__SeekableStreamDecoder *decoder)
-{
-       FLAC__SeekableStreamDecoderState state = FLAC__seekable_stream_decoder_get_state(decoder);
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)state, FLAC__SeekableStreamDecoderStateString[state]);
-       if(state == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
-               FLAC__StreamDecoderState state_ = FLAC__seekable_stream_decoder_get_stream_decoder_state(decoder);
-               printf("      stream decoder state = %u (%s)\n", (unsigned)state_, FLAC__StreamDecoderStateString[state_]);
-       }
-
-       return false;
-}
-
-static FLAC__bool die_f_(const char *msg, const FLAC__FileDecoder *decoder)
-{
-       FLAC__FileDecoderState state = FLAC__file_decoder_get_state(decoder);
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)state, FLAC__FileDecoderStateString[state]);
-       if(state == FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) {
-               FLAC__SeekableStreamDecoderState state_ = FLAC__file_decoder_get_seekable_stream_decoder_state(decoder);
-               printf("      seekable stream decoder state = %u (%s)\n", (unsigned)state, FLAC__SeekableStreamDecoderStateString[state_]);
-               if(state_ == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
-                       FLAC__StreamDecoderState state__ = FLAC__file_decoder_get_stream_decoder_state(decoder);
-                       printf("      stream decoder state = %u (%s)\n", (unsigned)state__, FLAC__StreamDecoderStateString[state__]);
-               }
-       }
-
-       return false;
-}
-
 static void init_metadata_blocks_()
 {
        mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
@@ -145,7 +115,7 @@ static FLAC__bool generate_file_()
 
 static FLAC__StreamDecoderReadStatus stream_decoder_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
 {
-       stream_decoder_client_data_struct *dcd = (stream_decoder_client_data_struct*)client_data;
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
        const unsigned requested_bytes = *bytes;
 
        (void)decoder;
@@ -178,9 +148,92 @@ static FLAC__StreamDecoderReadStatus stream_decoder_read_callback_(const FLAC__S
                return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
 }
 
+static FLAC__StreamDecoderSeekStatus stream_decoder_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+
+       (void)decoder;
+
+       if(0 == dcd) {
+               printf("ERROR: client_data in seek callback is NULL\n");
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+       }
+
+       if(dcd->error_occurred)
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+
+       if(fseeko(dcd->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
+               dcd->error_occurred = true;
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+       }
+
+       return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+static FLAC__StreamDecoderTellStatus stream_decoder_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+       off_t offset;
+
+       (void)decoder;
+
+       if(0 == dcd) {
+               printf("ERROR: client_data in tell callback is NULL\n");
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+       }
+
+       if(dcd->error_occurred)
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+
+       offset = ftello(dcd->file);
+       *absolute_byte_offset = (FLAC__uint64)offset;
+
+       if(offset < 0) {
+               dcd->error_occurred = true;
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+       }
+
+       return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+}
+
+static FLAC__StreamDecoderLengthStatus stream_decoder_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
+{
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+
+       (void)decoder;
+
+       if(0 == dcd) {
+               printf("ERROR: client_data in length callback is NULL\n");
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+       }
+
+       if(dcd->error_occurred)
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+
+       *stream_length = (FLAC__uint64)flacfilesize_;
+       return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+}
+
+static FLAC__bool stream_decoder_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data)
+{
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+
+       (void)decoder;
+
+       if(0 == dcd) {
+               printf("ERROR: client_data in eof callback is NULL\n");
+               return true;
+       }
+
+       if(dcd->error_occurred)
+               return true;
+
+       return feof(dcd->file);
+}
+
 static FLAC__StreamDecoderWriteStatus stream_decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
-       stream_decoder_client_data_struct *dcd = (stream_decoder_client_data_struct*)client_data;
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
 
        (void)decoder, (void)buffer;
 
@@ -205,7 +258,7 @@ static FLAC__StreamDecoderWriteStatus stream_decoder_write_callback_(const FLAC_
 
 static void stream_decoder_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
-       stream_decoder_client_data_struct *dcd = (stream_decoder_client_data_struct*)client_data;
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
 
        (void)decoder;
 
@@ -235,7 +288,7 @@ static void stream_decoder_metadata_callback_(const FLAC__StreamDecoder *decoder
 
 static void stream_decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
-       stream_decoder_client_data_struct *dcd = (stream_decoder_client_data_struct*)client_data;
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
 
        (void)decoder;
 
@@ -250,31 +303,49 @@ static void stream_decoder_error_callback_(const FLAC__StreamDecoder *decoder, F
        }
 }
 
-static FLAC__bool stream_decoder_test_respond_(FLAC__StreamDecoder *decoder, stream_decoder_client_data_struct *dcd)
+static FLAC__bool stream_decoder_test_respond_(FLAC__StreamDecoder *decoder, StreamDecoderClientData *dcd)
 {
-       if(!FLAC__stream_decoder_set_read_callback(decoder, stream_decoder_read_callback_))
-               return die_s_("at FLAC__stream_decoder_set_read_callback(), returned false", decoder);
-
-       if(!FLAC__stream_decoder_set_write_callback(decoder, stream_decoder_write_callback_))
-               return die_s_("at FLAC__stream_decoder_set_write_callback(), returned false", decoder);
-
-       if(!FLAC__stream_decoder_set_metadata_callback(decoder, stream_decoder_metadata_callback_))
-               return die_s_("at FLAC__stream_decoder_set_metadata_callback(), returned false", decoder);
+       FLAC__StreamDecoderInitStatus init_status;
 
-       if(!FLAC__stream_decoder_set_error_callback(decoder, stream_decoder_error_callback_))
-               return die_s_("at FLAC__stream_decoder_set_error_callback(), returned false", decoder);
+       if(!FLAC__stream_decoder_set_md5_checking(decoder, true))
+               return die_s_("at FLAC__stream_decoder_set_md5_checking(), returned false", decoder);
 
-       if(!FLAC__stream_decoder_set_client_data(decoder, dcd))
-               return die_s_("at FLAC__stream_decoder_set_client_data(), returned false", decoder);
-
-       printf("testing FLAC__stream_decoder_init()... ");
-       if(FLAC__stream_decoder_init(decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
+       /* for FLAC__stream_encoder_init_FILE(), the FLAC__stream_encoder_finish() closes the file so we have to keep re-opening: */
+       if(dcd->layer == LAYER_FILE) {
+               printf("opening FLAC file... ");
+               dcd->file = fopen(flacfilename_, "rb");
+               if(0 == dcd->file) {
+                       printf("ERROR (%s)\n", strerror(errno));
+                       return false;
+               }
+               printf("OK\n");
+       }
+
+       printf("testing FLAC__stream_decoder_init_stream()... ");
+       switch(dcd->layer) {
+               case LAYER_STREAM:
+                       init_status = FLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
+                       break;
+               case LAYER_SEEKABLE_STREAM:
+                       init_status = FLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, stream_decoder_seek_callback_, stream_decoder_tell_callback_, stream_decoder_length_callback_, stream_decoder_eof_callback_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
+                       break;
+               case LAYER_FILE:
+                       init_status = FLAC__stream_decoder_init_FILE(decoder, dcd->file, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
+                       break;
+               case LAYER_FILENAME:
+                       init_status = FLAC__stream_decoder_init_file(decoder, flacfilename_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
+                       break;
+               default:
+                       die_("internal error 000");
+                       return false;
+       }
+       if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
                return die_s_(0, decoder);
        printf("OK\n");
 
        dcd->current_metadata_number = 0;
 
-       if(fseeko(dcd->file, 0, SEEK_SET) < 0) {
+       if(dcd->layer < LAYER_FILE && fseeko(dcd->file, 0, SEEK_SET) < 0) {
                printf("FAILED rewinding input, errno = %d\n", errno);
                return false;
        }
@@ -291,13 +362,16 @@ static FLAC__bool stream_decoder_test_respond_(FLAC__StreamDecoder *decoder, str
        return true;
 }
 
-static FLAC__bool test_stream_decoder()
+static FLAC__bool test_stream_decoder(Layer layer)
 {
        FLAC__StreamDecoder *decoder;
        FLAC__StreamDecoderState state;
-       stream_decoder_client_data_struct decoder_client_data;
+       StreamDecoderClientData decoder_client_data;
+       FLAC__bool expect;
 
-       printf("\n+++ libFLAC unit test: FLAC__StreamDecoder\n\n");
+       decoder_client_data.layer = layer;
+
+       printf("\n+++ libFLAC unit test: FLAC__StreamDecoder (layer: %s)\n\n", LayerString[layer]);
 
        printf("testing FLAC__stream_decoder_new()... ");
        decoder = FLAC__stream_decoder_new();
@@ -319,9 +393,27 @@ static FLAC__bool test_stream_decoder()
        }
        printf("OK\n");
 
-       printf("testing FLAC__stream_decoder_init()... ");
-       if(FLAC__stream_decoder_init(decoder) == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
-               return die_s_(0, decoder);
+       switch(layer) {
+               case LAYER_STREAM:
+               case LAYER_SEEKABLE_STREAM:
+                       printf("testing FLAC__stream_decoder_init_stream()... ");
+                       if(FLAC__stream_decoder_init_stream(decoder, 0, 0, 0, 0, 0, 0, 0, 0, 0) != FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILE:
+                       printf("testing FLAC__stream_decoder_init_FILE()... ");
+                       if(FLAC__stream_decoder_init_FILE(decoder, stdin, 0, 0, 0, 0) != FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing FLAC__stream_decoder_init_file()... ");
+                       if(FLAC__stream_decoder_init_file(decoder, flacfilename_, 0, 0, 0, 0) != FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS)
+                               return die_s_(0, decoder);
+                       break;
+               default:
+                       die_("internal error 003");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing FLAC__stream_decoder_delete()... ");
@@ -339,34 +431,46 @@ static FLAC__bool test_stream_decoder()
        }
        printf("OK\n");
 
-       printf("testing FLAC__stream_decoder_set_read_callback()... ");
-       if(!FLAC__stream_decoder_set_read_callback(decoder, stream_decoder_read_callback_))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__stream_decoder_set_write_callback()... ");
-       if(!FLAC__stream_decoder_set_write_callback(decoder, stream_decoder_write_callback_))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__stream_decoder_set_metadata_callback()... ");
-       if(!FLAC__stream_decoder_set_metadata_callback(decoder, stream_decoder_metadata_callback_))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__stream_decoder_set_error_callback()... ");
-       if(!FLAC__stream_decoder_set_error_callback(decoder, stream_decoder_error_callback_))
+       printf("testing FLAC__stream_decoder_set_md5_checking()... ");
+       if(!FLAC__stream_decoder_set_md5_checking(decoder, true))
                return die_s_("returned false", decoder);
        printf("OK\n");
 
-       printf("testing FLAC__stream_decoder_set_client_data()... ");
-       if(!FLAC__stream_decoder_set_client_data(decoder, &decoder_client_data))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__stream_decoder_init()... ");
-       if(FLAC__stream_decoder_init(decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
-               return die_s_(0, decoder);
+       if(layer < LAYER_FILENAME) {
+               printf("opening FLAC file... ");
+               decoder_client_data.file = fopen(flacfilename_, "rb");
+               if(0 == decoder_client_data.file) {
+                       printf("ERROR (%s)\n", strerror(errno));
+                       return false;
+               }
+               printf("OK\n");
+       }
+
+       switch(layer) {
+               case LAYER_STREAM:
+                       printf("testing FLAC__stream_decoder_init_stream()... ");
+                       if(FLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_SEEKABLE_STREAM:
+                       printf("testing FLAC__stream_decoder_init_stream()... ");
+                       if(FLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, stream_decoder_seek_callback_, stream_decoder_tell_callback_, stream_decoder_length_callback_, stream_decoder_eof_callback_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILE:
+                       printf("testing FLAC__stream_decoder_init_FILE()... ");
+                       if(FLAC__stream_decoder_init_FILE(decoder, decoder_client_data.file, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing FLAC__stream_decoder_init_file()... ");
+                       if(FLAC__stream_decoder_init_file(decoder, flacfilename_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               default:
+                       die_("internal error 009");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing FLAC__stream_decoder_get_state()... ");
@@ -377,10 +481,9 @@ static FLAC__bool test_stream_decoder()
        decoder_client_data.ignore_errors = false;
        decoder_client_data.error_occurred = false;
 
-       printf("opening FLAC file... ");
-       decoder_client_data.file = fopen(flacfilename_, "rb");
-       if(0 == decoder_client_data.file) {
-               printf("ERROR (%s)\n", strerror(errno));
+       printf("testing FLAC__stream_decoder_get_md5_checking()... ");
+       if(!FLAC__stream_decoder_get_md5_checking(decoder)) {
+               printf("FAILED, returned false, expected true\n");
                return false;
        }
        printf("OK\n");
@@ -400,23 +503,37 @@ static FLAC__bool test_stream_decoder()
                return die_s_("returned false", decoder);
        printf("OK\n");
 
-       printf("testing FLAC__stream_decoder_flush()... ");
-       if(!FLAC__stream_decoder_flush(decoder))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
+       if(layer < LAYER_FILE) {
+               printf("testing FLAC__stream_decoder_flush()... ");
+               if(!FLAC__stream_decoder_flush(decoder))
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
 
-       decoder_client_data.ignore_errors = true;
-       printf("testing FLAC__stream_decoder_process_single()... ");
-       if(!FLAC__stream_decoder_process_single(decoder))
-               return die_s_("returned false", decoder);
+               decoder_client_data.ignore_errors = true;
+               printf("testing FLAC__stream_decoder_process_single()... ");
+               if(!FLAC__stream_decoder_process_single(decoder))
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+               decoder_client_data.ignore_errors = false;
+       }
+
+       expect = (layer != LAYER_STREAM);
+       printf("testing FLAC__stream_decoder_seek_absolute()... ");
+       if(FLAC__stream_decoder_seek_absolute(decoder, 0) != expect)
+               return die_s_(expect? "returned false" : "returned true", decoder);
        printf("OK\n");
-       decoder_client_data.ignore_errors = false;
 
        printf("testing FLAC__stream_decoder_process_until_end_of_stream()... ");
        if(!FLAC__stream_decoder_process_until_end_of_stream(decoder))
                return die_s_("returned false", decoder);
        printf("OK\n");
 
+       expect = (layer != LAYER_STREAM);
+       printf("testing FLAC__stream_decoder_seek_absolute()... ");
+       if(FLAC__stream_decoder_seek_absolute(decoder, 0) != expect)
+               return die_s_(expect? "returned false" : "returned true", decoder);
+       printf("OK\n");
+
        printf("testing FLAC__stream_decoder_get_channels()... ");
        {
                unsigned channels = FLAC__stream_decoder_get_channels(decoder);
@@ -450,8 +567,10 @@ static FLAC__bool test_stream_decoder()
        printf("testing FLAC__stream_decoder_get_blocksize()... ");
        {
                unsigned blocksize = FLAC__stream_decoder_get_blocksize(decoder);
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
+               /* value could be anything since we're at the last block, so accept any reasonable answer */
+               printf("returned %u... %s\n", blocksize, blocksize>0? "OK" : "FAILED");
+               if(blocksize == 0)
+                       return false;
        }
 
        printf("testing FLAC__stream_decoder_get_channel_assignment()... ");
@@ -460,30 +579,35 @@ static FLAC__bool test_stream_decoder()
                printf("returned %u (%s)... OK\n", (unsigned)ca, FLAC__ChannelAssignmentString[ca]);
        }
 
-       printf("testing FLAC__stream_decoder_reset()... ");
-       if(!FLAC__stream_decoder_reset(decoder)) {
-               state = FLAC__stream_decoder_get_state(decoder);
-               printf("FAILED, returned false, state = %u (%s)\n", state, FLAC__StreamDecoderStateString[state]);
-               return false;
-       }
-       printf("OK\n");
+       if(layer < LAYER_FILE) {
+               printf("testing FLAC__stream_decoder_reset()... ");
+               if(!FLAC__stream_decoder_reset(decoder)) {
+                       state = FLAC__stream_decoder_get_state(decoder);
+                       printf("FAILED, returned false, state = %u (%s)\n", state, FLAC__StreamDecoderStateString[state]);
+                       return false;
+               }
+               printf("OK\n");
+
+               if(layer == LAYER_STREAM) {
+                       /* after a reset() we have to rewind the input ourselves */
+                       printf("rewinding input... ");
+                       if(fseeko(decoder_client_data.file, 0, SEEK_SET) < 0) {
+                               printf("FAILED, errno = %d\n", errno);
+                               return false;
+                       }
+                       printf("OK\n");
+               }
 
-       decoder_client_data.current_metadata_number = 0;
+               decoder_client_data.current_metadata_number = 0;
 
-       printf("rewinding input... ");
-       if(fseeko(decoder_client_data.file, 0, SEEK_SET) < 0) {
-               printf("FAILED, errno = %d\n", errno);
-               return false;
+               printf("testing FLAC__stream_decoder_process_until_end_of_stream()... ");
+               if(!FLAC__stream_decoder_process_until_end_of_stream(decoder))
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
        }
-       printf("OK\n");
-
-       printf("testing FLAC__stream_decoder_process_until_end_of_stream()... ");
-       if(!FLAC__stream_decoder_process_until_end_of_stream(decoder))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
 
        printf("testing FLAC__stream_decoder_finish()... ");
-       FLAC__stream_decoder_finish(decoder);
+       (void) FLAC__stream_decoder_finish(decoder);
        printf("OK\n");
 
        /*
@@ -772,1298 +896,34 @@ static FLAC__bool test_stream_decoder()
        if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
                return false;
 
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
+       if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
+               fclose(decoder_client_data.file);
 
        printf("testing FLAC__stream_decoder_delete()... ");
        FLAC__stream_decoder_delete(decoder);
        printf("OK\n");
 
-       fclose(decoder_client_data.file);
-
        printf("\nPASSED!\n");
 
        return true;
 }
 
-static FLAC__SeekableStreamDecoderReadStatus seekable_stream_decoder_read_callback_(const FLAC__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:
-                       return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-               case FLAC__STREAM_DECODER_READ_STATUS_ABORT:
-               case FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM:
-                       return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-               default:
-                       FLAC__ASSERT(0);
-                       return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-       }
-}
-
-static FLAC__SeekableStreamDecoderSeekStatus seekable_stream_decoder_seek_callback_(const FLAC__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;
-
-       (void)decoder;
-
-       if(0 == dcd) {
-               printf("ERROR: client_data in seek callback is NULL\n");
-               return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-       }
-
-       if(dcd->error_occurred)
-               return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-
-       if(fseeko(dcd->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
-               dcd->error_occurred = true;
-               return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-       }
-
-       return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-static FLAC__SeekableStreamDecoderTellStatus seekable_stream_decoder_tell_callback_(const FLAC__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;
-       off_t offset;
-
-       (void)decoder;
-
-       if(0 == dcd) {
-               printf("ERROR: client_data in tell callback is NULL\n");
-               return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-       }
-
-       if(dcd->error_occurred)
-               return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-
-       offset = ftello(dcd->file);
-       *absolute_byte_offset = (FLAC__uint64)offset;
-
-       if(offset < 0) {
-               dcd->error_occurred = true;
-               return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-       }
-
-       return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
-}
-
-static FLAC__SeekableStreamDecoderLengthStatus seekable_stream_decoder_length_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
-{
-       seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data;
-
-       (void)decoder;
-
-       if(0 == dcd) {
-               printf("ERROR: client_data in length callback is NULL\n");
-               return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
-       }
-
-       if(dcd->error_occurred)
-               return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
-
-       *stream_length = (FLAC__uint64)flacfilesize_;
-       return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
-}
-
-static FLAC__bool seekable_stream_decoder_eof_callback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data)
-{
-       seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data;
-
-       (void)decoder;
-
-       if(0 == dcd) {
-               printf("ERROR: client_data in eof callback is NULL\n");
-               return true;
-       }
-
-       if(dcd->error_occurred)
-               return true;
-
-       return feof(dcd->file);
-}
-
-static FLAC__StreamDecoderWriteStatus seekable_stream_decoder_write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       (void)decoder;
-       return stream_decoder_write_callback_(0, frame, buffer, client_data);
-}
-
-static void seekable_stream_decoder_metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       (void)decoder;
-       stream_decoder_metadata_callback_(0, metadata, client_data);
-}
-
-static void seekable_stream_decoder_error_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       (void)decoder;
-       stream_decoder_error_callback_(0, status, client_data);
-}
-
-static FLAC__bool seekable_stream_decoder_test_respond_(FLAC__SeekableStreamDecoder *decoder, seekable_stream_decoder_client_data_struct *dcd)
+FLAC__bool test_decoders()
 {
-       if(!FLAC__seekable_stream_decoder_set_read_callback(decoder, seekable_stream_decoder_read_callback_))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_read_callback(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_seek_callback(decoder, seekable_stream_decoder_seek_callback_))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_seek_callback(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_tell_callback(decoder, seekable_stream_decoder_tell_callback_))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_tell_callback(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_length_callback(decoder, seekable_stream_decoder_length_callback_))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_length_callback(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_eof_callback(decoder, seekable_stream_decoder_eof_callback_))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_eof_callback(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_write_callback(decoder, seekable_stream_decoder_write_callback_))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_write_callback(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_metadata_callback(decoder, seekable_stream_decoder_metadata_callback_))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_metadata_callback(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_error_callback(decoder, seekable_stream_decoder_error_callback_))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_error_callback(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_client_data(decoder, dcd))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_client_data(), returned false", decoder);
-
-       if(!FLAC__seekable_stream_decoder_set_md5_checking(decoder, true))
-               return die_ss_("at FLAC__seekable_stream_decoder_set_md5_checking(), returned false", decoder);
-
-       printf("testing FLAC__seekable_stream_decoder_init()... ");
-       if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK)
-               return die_ss_(0, decoder);
-       printf("OK\n");
+       init_metadata_blocks_();
+       if(!generate_file_())
+               return false;
 
-       dcd->current_metadata_number = 0;
-
-       if(fseeko(dcd->file, 0, SEEK_SET) < 0) {
-               printf("FAILED rewinding input, errno = %d\n", errno);
-               return false;
-       }
-
-       printf("testing FLAC__seekable_stream_decoder_process_until_end_of_stream()... ");
-       if(!FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_finish()... ");
-       (void) FLAC__seekable_stream_decoder_finish(decoder);
-       printf("OK\n");
-
-       return true;
-}
-
-static FLAC__bool test_seekable_stream_decoder()
-{
-       FLAC__SeekableStreamDecoder *decoder;
-       FLAC__SeekableStreamDecoderState state;
-       FLAC__StreamDecoderState sstate;
-       seekable_stream_decoder_client_data_struct decoder_client_data;
-
-       printf("\n+++ libFLAC unit test: FLAC__SeekableStreamDecoder\n\n");
-
-       printf("testing FLAC__seekable_stream_decoder_new()... ");
-       decoder = FLAC__seekable_stream_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_delete()... ");
-       FLAC__seekable_stream_decoder_delete(decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_new()... ");
-       decoder = FLAC__seekable_stream_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_init()... ");
-       if(FLAC__seekable_stream_decoder_init(decoder) == FLAC__SEEKABLE_STREAM_DECODER_OK)
-               return die_ss_(0, decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_delete()... ");
-       FLAC__seekable_stream_decoder_delete(decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-
-       printf("testing FLAC__seekable_stream_decoder_new()... ");
-       decoder = FLAC__seekable_stream_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_read_callback()... ");
-       if(!FLAC__seekable_stream_decoder_set_read_callback(decoder, seekable_stream_decoder_read_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_seek_callback()... ");
-       if(!FLAC__seekable_stream_decoder_set_seek_callback(decoder, seekable_stream_decoder_seek_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_tell_callback()... ");
-       if(!FLAC__seekable_stream_decoder_set_tell_callback(decoder, seekable_stream_decoder_tell_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_length_callback()... ");
-       if(!FLAC__seekable_stream_decoder_set_length_callback(decoder, seekable_stream_decoder_length_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_eof_callback()... ");
-       if(!FLAC__seekable_stream_decoder_set_eof_callback(decoder, seekable_stream_decoder_eof_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_write_callback()... ");
-       if(!FLAC__seekable_stream_decoder_set_write_callback(decoder, seekable_stream_decoder_write_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_callback()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_callback(decoder, seekable_stream_decoder_metadata_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_error_callback()... ");
-       if(!FLAC__seekable_stream_decoder_set_error_callback(decoder, seekable_stream_decoder_error_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_client_data()... ");
-       if(!FLAC__seekable_stream_decoder_set_client_data(decoder, &decoder_client_data))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_md5_checking()... ");
-       if(!FLAC__seekable_stream_decoder_set_md5_checking(decoder, true))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_init()... ");
-       if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK)
-               return die_ss_(0, decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_get_state()... ");
-       state = FLAC__seekable_stream_decoder_get_state(decoder);
-       printf("returned state = %u (%s)... OK\n", state, FLAC__SeekableStreamDecoderStateString[state]);
-
-       printf("testing FLAC__seekable_stream_decoder_get_stream_decoder_state()... ");
-       sstate = FLAC__seekable_stream_decoder_get_stream_decoder_state(decoder);
-       printf("returned state = %u (%s)... OK\n", sstate, FLAC__StreamDecoderStateString[sstate]);
-
-       decoder_client_data.current_metadata_number = 0;
-       decoder_client_data.ignore_errors = false;
-       decoder_client_data.error_occurred = false;
-
-       printf("opening FLAC file... ");
-       decoder_client_data.file = fopen(flacfilename_, "rb");
-       if(0 == decoder_client_data.file) {
-               printf("ERROR (%s)\n", strerror(errno));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_get_md5_checking()... ");
-       if(!FLAC__seekable_stream_decoder_get_md5_checking(decoder)) {
-               printf("FAILED, returned false, expected true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_process_until_end_of_metadata()... ");
-       if(!FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_process_single()... ");
-       if(!FLAC__seekable_stream_decoder_process_single(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_skip_single_frame()... ");
-       if(!FLAC__seekable_stream_decoder_skip_single_frame(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_flush()... ");
-       if(!FLAC__seekable_stream_decoder_flush(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       decoder_client_data.ignore_errors = true;
-       printf("testing FLAC__seekable_stream_decoder_process_single()... ");
-       if(!FLAC__seekable_stream_decoder_process_single(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-       decoder_client_data.ignore_errors = false;
-
-       printf("testing FLAC__seekable_stream_decoder_seek_absolute()... ");
-       if(!FLAC__seekable_stream_decoder_seek_absolute(decoder, 0))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_process_until_end_of_stream()... ");
-       if(!FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_get_channels()... ");
-       {
-               unsigned channels = FLAC__seekable_stream_decoder_get_channels(decoder);
-               if(channels != streaminfo_.data.stream_info.channels) {
-                       printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_get_bits_per_sample()... ");
-       {
-               unsigned bits_per_sample = FLAC__seekable_stream_decoder_get_bits_per_sample(decoder);
-               if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
-                       printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_get_sample_rate()... ");
-       {
-               unsigned sample_rate = FLAC__seekable_stream_decoder_get_sample_rate(decoder);
-               if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
-                       printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_get_blocksize()... ");
-       {
-               unsigned blocksize = FLAC__seekable_stream_decoder_get_blocksize(decoder);
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
-       }
-
-       printf("testing FLAC__seekable_stream_decoder_get_channel_assignment()... ");
-       {
-               FLAC__ChannelAssignment ca = FLAC__seekable_stream_decoder_get_channel_assignment(decoder);
-               printf("returned %u (%s)... OK\n", (unsigned)ca, FLAC__ChannelAssignmentString[ca]);
-       }
-
-       printf("testing FLAC__seekable_stream_decoder_reset()... ");
-       if(!FLAC__seekable_stream_decoder_reset(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       decoder_client_data.current_metadata_number = 0;
-
-       printf("rewinding input... ");
-       if(fseeko(decoder_client_data.file, 0, SEEK_SET) < 0) {
-               printf("FAILED, errno = %d\n", errno);
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_process_until_end_of_stream()... ");
-       if(!FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_finish()... ");
-       (void) FLAC__seekable_stream_decoder_finish(decoder);
-       printf("OK\n");
-
-       /*
-        * respond all
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore VORBIS_COMMENT
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore(VORBIS_COMMENT)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore(APPLICATION)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_application(of app block #2)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder, application2_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond VORBIS_COMMENT
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond(VORBIS_COMMENT)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond(APPLICATION)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_application(of app block #2)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder, application2_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION, respond APPLICATION id of app#1
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore(APPLICATION)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
-        */
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_respond(APPLICATION)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       printf("testing FLAC__seekable_stream_decoder_delete()... ");
-       FLAC__seekable_stream_decoder_delete(decoder);
-       printf("OK\n");
-
-       fclose(decoder_client_data.file);
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-static FLAC__StreamDecoderWriteStatus file_decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       (void)decoder;
-       return stream_decoder_write_callback_(0, frame, buffer, client_data);
-}
-
-static void file_decoder_metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       (void)decoder;
-       stream_decoder_metadata_callback_(0, metadata, client_data);
-}
-
-static void file_decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       (void)decoder;
-       stream_decoder_error_callback_(0, status, client_data);
-}
-
-static FLAC__bool file_decoder_test_respond_(FLAC__FileDecoder *decoder, file_decoder_client_data_struct *dcd)
-{
-       if(!FLAC__file_decoder_set_write_callback(decoder, file_decoder_write_callback_))
-               return die_f_("at FLAC__file_decoder_set_write_callback(), returned false", decoder);
-
-       if(!FLAC__file_decoder_set_metadata_callback(decoder, file_decoder_metadata_callback_))
-               return die_f_("at FLAC__file_decoder_set_metadata_callback(), returned false", decoder);
-
-       if(!FLAC__file_decoder_set_error_callback(decoder, file_decoder_error_callback_))
-               return die_f_("at FLAC__file_decoder_set_error_callback(), returned false", decoder);
-
-       if(!FLAC__file_decoder_set_client_data(decoder, dcd))
-               return die_f_("at FLAC__file_decoder_set_client_data(), returned false", decoder);
-
-       if(!FLAC__file_decoder_set_filename(decoder, flacfilename_))
-               return die_f_("at FLAC__file_decoder_set_filename(), returned false", decoder);
-
-       if(!FLAC__file_decoder_set_md5_checking(decoder, true))
-               return die_f_("at FLAC__file_decoder_set_md5_checking(), returned false", decoder);
-
-       printf("testing FLAC__file_decoder_init()... ");
-       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
-               return die_f_(0, decoder);
-       printf("OK\n");
-
-       dcd->current_metadata_number = 0;
-
-       printf("testing FLAC__file_decoder_process_until_end_of_file()... ");
-       if(!FLAC__file_decoder_process_until_end_of_file(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_finish()... ");
-       (void) FLAC__file_decoder_finish(decoder);
-       printf("OK\n");
-
-       return true;
-}
-
-static FLAC__bool test_file_decoder()
-{
-       FLAC__FileDecoder *decoder;
-       FLAC__FileDecoderState state;
-       FLAC__SeekableStreamDecoderState ssstate;
-       FLAC__StreamDecoderState sstate;
-       seekable_stream_decoder_client_data_struct decoder_client_data;
-
-       printf("\n+++ libFLAC unit test: FLAC__FileDecoder\n\n");
-
-       printf("testing FLAC__file_decoder_new()... ");
-       decoder = FLAC__file_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_delete()... ");
-       FLAC__file_decoder_delete(decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_new()... ");
-       decoder = FLAC__file_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_init()... ");
-       if(FLAC__file_decoder_init(decoder) == FLAC__FILE_DECODER_OK)
-               return die_f_(0, decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_delete()... ");
-       FLAC__file_decoder_delete(decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-
-       printf("testing FLAC__file_decoder_new()... ");
-       decoder = FLAC__file_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_write_callback()... ");
-       if(!FLAC__file_decoder_set_write_callback(decoder, file_decoder_write_callback_))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_callback()... ");
-       if(!FLAC__file_decoder_set_metadata_callback(decoder, file_decoder_metadata_callback_))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_error_callback()... ");
-       if(!FLAC__file_decoder_set_error_callback(decoder, file_decoder_error_callback_))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_client_data()... ");
-       if(!FLAC__file_decoder_set_client_data(decoder, &decoder_client_data))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_filename()... ");
-       if(!FLAC__file_decoder_set_filename(decoder, flacfilename_))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_md5_checking()... ");
-       if(!FLAC__file_decoder_set_md5_checking(decoder, true))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_init()... ");
-       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
-               return die_f_(0, decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_get_state()... ");
-       state = FLAC__file_decoder_get_state(decoder);
-       printf("returned state = %u (%s)... OK\n", state, FLAC__FileDecoderStateString[state]);
-
-       printf("testing FLAC__file_decoder_get_seekable_stream_decoder_state()... ");
-       ssstate = FLAC__file_decoder_get_seekable_stream_decoder_state(decoder);
-       printf("returned state = %u (%s)... OK\n", ssstate, FLAC__SeekableStreamDecoderStateString[ssstate]);
-
-       printf("testing FLAC__file_decoder_get_stream_decoder_state()... ");
-       sstate = FLAC__file_decoder_get_stream_decoder_state(decoder);
-       printf("returned state = %u (%s)... OK\n", sstate, FLAC__StreamDecoderStateString[sstate]);
-
-       decoder_client_data.current_metadata_number = 0;
-       decoder_client_data.ignore_errors = false;
-       decoder_client_data.error_occurred = false;
-
-       printf("testing FLAC__file_decoder_get_md5_checking()... ");
-       if(!FLAC__file_decoder_get_md5_checking(decoder)) {
-               printf("FAILED, returned false, expected true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_process_until_end_of_metadata()... ");
-       if(!FLAC__file_decoder_process_until_end_of_metadata(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_process_single()... ");
-       if(!FLAC__file_decoder_process_single(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_skip_single_frame()... ");
-       if(!FLAC__file_decoder_skip_single_frame(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_seek_absolute()... ");
-       if(!FLAC__file_decoder_seek_absolute(decoder, 0))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_process_until_end_of_file()... ");
-       if(!FLAC__file_decoder_process_until_end_of_file(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_get_channels()... ");
-       {
-               unsigned channels = FLAC__file_decoder_get_channels(decoder);
-               if(channels != streaminfo_.data.stream_info.channels) {
-                       printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_get_bits_per_sample()... ");
-       {
-               unsigned bits_per_sample = FLAC__file_decoder_get_bits_per_sample(decoder);
-               if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
-                       printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_get_sample_rate()... ");
-       {
-               unsigned sample_rate = FLAC__file_decoder_get_sample_rate(decoder);
-               if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
-                       printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_get_blocksize()... ");
-       {
-               unsigned blocksize = FLAC__file_decoder_get_blocksize(decoder);
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
-       }
-
-       printf("testing FLAC__file_decoder_get_channel_assignment()... ");
-       {
-               FLAC__ChannelAssignment ca = FLAC__file_decoder_get_channel_assignment(decoder);
-               printf("returned %u (%s)... OK\n", (unsigned)ca, FLAC__ChannelAssignmentString[ca]);
-       }
-
-       printf("testing FLAC__file_decoder_finish()... ");
-       (void) FLAC__file_decoder_finish(decoder);
-       printf("OK\n");
-
-       /*
-        * respond all
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore VORBIS_COMMENT
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore(VORBIS_COMMENT)... ");
-       if(!FLAC__file_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore(APPLICATION)... ");
-       if(!FLAC__file_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_application(of app block #2)... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_application(decoder, application2_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond VORBIS_COMMENT
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_respond(VORBIS_COMMENT)... ");
-       if(!FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_respond(APPLICATION)... ");
-       if(!FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!FLAC__file_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!FLAC__file_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_application(of app block #2)... ");
-       if(!FLAC__file_decoder_set_metadata_respond_application(decoder, application2_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION, respond APPLICATION id of app#1
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!FLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore(APPLICATION)... ");
-       if(!FLAC__file_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!FLAC__file_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
-        */
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_respond(APPLICATION)... ");
-       if(!FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!FLAC__file_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       printf("testing FLAC__file_decoder_delete()... ");
-       FLAC__file_decoder_delete(decoder);
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-FLAC__bool test_decoders()
-{
-       init_metadata_blocks_();
-       if(!generate_file_())
+       if(!test_stream_decoder(LAYER_STREAM))
                return false;
 
-       if(!test_stream_decoder())
+       if(!test_stream_decoder(LAYER_SEEKABLE_STREAM))
                return false;
 
-       if(!test_seekable_stream_decoder())
+       if(!test_stream_decoder(LAYER_FILE))
                return false;
 
-       if(!test_file_decoder())
+       if(!test_stream_decoder(LAYER_FILENAME))
                return false;
 
        (void) grabbag__file_remove_file(flacfilename_);
index 34ec1ae..053695f 100644 (file)
 #  include <config.h>
 #endif
 
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include "encoders.h"
-#include "file_utils.h"
-#include "metadata_utils.h"
 #include "FLAC/assert.h"
-#include "FLAC/file_encoder.h"
-#include "FLAC/seekable_stream_encoder.h"
 #include "FLAC/stream_encoder.h"
 #include "share/grabbag.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include "test_libs_common/file_utils_flac.h"
+#include "test_libs_common/metadata_utils.h"
+
+typedef enum {
+       LAYER_STREAM = 0, /* FLAC__stream_encoder_init_stream() without seeking */
+       LAYER_SEEKABLE_STREAM, /* FLAC__stream_encoder_init_stream() with seeking */
+       LAYER_FILE, /* FLAC__stream_encoder_init_FILE() */
+       LAYER_FILENAME /* FLAC__stream_encoder_init_file() */
+} Layer;
+
+static const char * const LayerString[] = {
+       "Stream",
+       "Seekable Stream",
+       "FILE*",
+       "Filename"
+};
 
 static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
 static FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_ };
 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
 static const char *flacfilename_ = "metadata.flac";
 
+static FLAC__bool die_(const char *msg)
+{
+       printf("ERROR: %s\n", msg);
+       return false;
+}
+
 static FLAC__bool die_s_(const char *msg, const FLAC__StreamEncoder *encoder)
 {
        FLAC__StreamEncoderState state = FLAC__stream_encoder_get_state(encoder);
@@ -55,54 +74,6 @@ static FLAC__bool die_s_(const char *msg, const FLAC__StreamEncoder *encoder)
        return false;
 }
 
-static FLAC__bool die_ss_(const char *msg, const FLAC__SeekableStreamEncoder *encoder)
-{
-       FLAC__SeekableStreamEncoderState state = FLAC__seekable_stream_encoder_get_state(encoder);
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)state, FLAC__SeekableStreamEncoderStateString[state]);
-       if(state == FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) {
-               FLAC__StreamEncoderState state_ = FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder);
-               printf("      stream encoder state = %u (%s)\n", (unsigned)state_, FLAC__StreamEncoderStateString[state_]);
-               if(state_ == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                       FLAC__StreamDecoderState dstate = FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder);
-                       printf("      verify decoder state = %u (%s)\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]);
-               }
-       }
-
-       return false;
-}
-
-static FLAC__bool die_f_(const char *msg, const FLAC__FileEncoder *encoder)
-{
-       FLAC__FileEncoderState state = FLAC__file_encoder_get_state(encoder);
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)state, FLAC__FileEncoderStateString[state]);
-       if(state == FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR) {
-               FLAC__SeekableStreamEncoderState state_ = FLAC__file_encoder_get_seekable_stream_encoder_state(encoder);
-               printf("      seekable stream encoder state = %u (%s)\n", (unsigned)state_, FLAC__SeekableStreamEncoderStateString[state_]);
-               if(state_ == FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) {
-                       FLAC__StreamEncoderState state__ = FLAC__file_encoder_get_stream_encoder_state(encoder);
-                       printf("      stream encoder state = %u (%s)\n", (unsigned)state__, FLAC__StreamEncoderStateString[state__]);
-                       if(state__ == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                               FLAC__StreamDecoderState dstate = FLAC__file_encoder_get_verify_decoder_state(encoder);
-                               printf("      verify decoder state = %u (%s)\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]);
-                       }
-               }
-       }
-
-       return false;
-}
-
 static void init_metadata_blocks_()
 {
        mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
@@ -119,23 +90,42 @@ static FLAC__StreamEncoderWriteStatus stream_encoder_write_callback_(const FLAC_
        return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
 }
 
+static FLAC__StreamEncoderSeekStatus stream_encoder_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+       (void)encoder, (void)absolute_byte_offset, (void)client_data;
+       return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+}
+
+static FLAC__StreamEncoderTellStatus stream_encoder_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+       (void)encoder, (void)client_data;
+       *absolute_byte_offset = 0;
+       return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+}
+
 static void stream_encoder_metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        (void)encoder, (void)metadata, (void)client_data;
 }
 
-static FLAC__bool test_stream_encoder()
+static void stream_encoder_progress_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
+{
+       (void)encoder, (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate, (void)client_data;
+}
+
+static FLAC__bool test_stream_encoder(Layer layer)
 {
        FLAC__StreamEncoder *encoder;
        FLAC__StreamEncoderState state;
        FLAC__StreamDecoderState dstate;
+       FILE *file = 0;
        FLAC__int32 samples[1024];
        FLAC__int32 *samples_array[1];
        unsigned i;
 
        samples_array[0] = samples;
 
-       printf("\n+++ libFLAC unit test: FLAC__StreamEncoder\n\n");
+       printf("\n+++ libFLAC unit test: FLAC__StreamEncoder (layer: %s)\n\n", LayerString[layer]);
 
        printf("testing FLAC__stream_encoder_new()... ");
        encoder = FLAC__stream_encoder_new();
@@ -235,24 +225,39 @@ static FLAC__bool test_stream_encoder()
                return die_s_("returned false", encoder);
        printf("OK\n");
 
-       printf("testing FLAC__stream_encoder_set_write_callback()... ");
-       if(!FLAC__stream_encoder_set_write_callback(encoder, stream_encoder_write_callback_))
-               return die_s_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__stream_encoder_set_metadata_callback()... ");
-       if(!FLAC__stream_encoder_set_metadata_callback(encoder, stream_encoder_metadata_callback_))
-               return die_s_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__stream_encoder_set_client_data()... ");
-       if(!FLAC__stream_encoder_set_client_data(encoder, 0))
-               return die_s_("returned false", encoder);
-       printf("OK\n");
+       switch(layer) {
+               case LAYER_STREAM:
+                       printf("testing FLAC__stream_encoder_init_stream()... ");
+                       if(FLAC__stream_encoder_init_stream(encoder, stream_encoder_write_callback_, /*seek_callback=*/0, /*tell_callback=*/0, stream_encoder_metadata_callback_, /*client_data=*/0) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_SEEKABLE_STREAM:
+                       printf("testing FLAC__stream_encoder_init_stream()... ");
+                       if(FLAC__stream_encoder_init_stream(encoder, stream_encoder_write_callback_, stream_encoder_seek_callback_, stream_encoder_tell_callback_, /*metadata_callback=*/0, /*client_data=*/0) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_FILE:
+                       printf("opening file for FLAC output... ");
+                       file = fopen(flacfilename_, "w+b");
+                       if(0 == file) {
+                               printf("ERROR (%s)\n", strerror(errno));
+                               return false;
+                       }
+                       printf("OK\n");
 
-       printf("testing FLAC__stream_encoder_init()... ");
-       if(FLAC__stream_encoder_init(encoder) != FLAC__STREAM_ENCODER_OK)
-               return die_s_(0, encoder);
+                       printf("testing FLAC__stream_encoder_init_FILE()... ");
+                       if(FLAC__stream_encoder_init_FILE(encoder, file, stream_encoder_progress_callback_, /*client_data=*/0) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing FLAC__stream_encoder_init_file()... ");
+                       if(FLAC__stream_encoder_init_file(encoder, flacfilename_, stream_encoder_progress_callback_, /*client_data=*/0) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               default:
+                       die_("internal error 001");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing FLAC__stream_encoder_get_state()... ");
@@ -420,653 +425,20 @@ static FLAC__bool test_stream_encoder()
        return true;
 }
 
-FLAC__SeekableStreamEncoderSeekStatus seekable_stream_encoder_seek_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-{
-       (void)encoder, (void)absolute_byte_offset, (void)client_data;
-       return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
-}
-
-FLAC__SeekableStreamEncoderTellStatus seekable_stream_encoder_tell_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-{
-       (void)encoder, (void)client_data;
-       *absolute_byte_offset = 0;
-       return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK;
-}
-
-FLAC__StreamEncoderWriteStatus seekable_stream_encoder_write_callback_(const FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       (void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
-       return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-}
-
-static FLAC__bool test_seekable_stream_encoder()
-{
-       FLAC__SeekableStreamEncoder *encoder;
-       FLAC__SeekableStreamEncoderState state;
-       FLAC__StreamEncoderState state_;
-       FLAC__StreamDecoderState dstate;
-       FLAC__int32 samples[1024];
-       FLAC__int32 *samples_array[1];
-       unsigned i;
-
-       samples_array[0] = samples;
-
-       printf("\n+++ libFLAC unit test: FLAC__SeekableStreamEncoder\n\n");
-
-       printf("testing FLAC__seekable_stream_encoder_new()... ");
-       encoder = FLAC__seekable_stream_encoder_new();
-       if(0 == encoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_verify()... ");
-       if(!FLAC__seekable_stream_encoder_set_verify(encoder, true))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_streamable_subset()... ");
-       if(!FLAC__seekable_stream_encoder_set_streamable_subset(encoder, true))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_do_mid_side_stereo()... ");
-       if(!FLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_loose_mid_side_stereo()... ");
-       if(!FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_channels()... ");
-       if(!FLAC__seekable_stream_encoder_set_channels(encoder, streaminfo_.data.stream_info.channels))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_bits_per_sample()... ");
-       if(!FLAC__seekable_stream_encoder_set_bits_per_sample(encoder, streaminfo_.data.stream_info.bits_per_sample))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_sample_rate()... ");
-       if(!FLAC__seekable_stream_encoder_set_sample_rate(encoder, streaminfo_.data.stream_info.sample_rate))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_blocksize()... ");
-       if(!FLAC__seekable_stream_encoder_set_blocksize(encoder, streaminfo_.data.stream_info.min_blocksize))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_max_lpc_order()... ");
-       if(!FLAC__seekable_stream_encoder_set_max_lpc_order(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_qlp_coeff_precision()... ");
-       if(!FLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search()... ");
-       if(!FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_do_escape_coding()... ");
-       if(!FLAC__seekable_stream_encoder_set_do_escape_coding(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_do_exhaustive_model_search()... ");
-       if(!FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_min_residual_partition_order()... ");
-       if(!FLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_max_residual_partition_order()... ");
-       if(!FLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_rice_parameter_search_dist()... ");
-       if(!FLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_total_samples_estimate()... ");
-       if(!FLAC__seekable_stream_encoder_set_total_samples_estimate(encoder, streaminfo_.data.stream_info.total_samples))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_metadata()... ");
-       if(!FLAC__seekable_stream_encoder_set_metadata(encoder, metadata_sequence_, num_metadata_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_seek_callback()... ");
-       if(!FLAC__seekable_stream_encoder_set_seek_callback(encoder, seekable_stream_encoder_seek_callback_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_tell_callback()... ");
-       if(!FLAC__seekable_stream_encoder_set_tell_callback(encoder, seekable_stream_encoder_tell_callback_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_write_callback()... ");
-       if(!FLAC__seekable_stream_encoder_set_write_callback(encoder, seekable_stream_encoder_write_callback_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_set_client_data()... ");
-       if(!FLAC__seekable_stream_encoder_set_client_data(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_init()... ");
-       if(FLAC__seekable_stream_encoder_init(encoder) != FLAC__SEEKABLE_STREAM_ENCODER_OK)
-               return die_ss_(0, encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_state()... ");
-       state = FLAC__seekable_stream_encoder_get_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)state, FLAC__SeekableStreamEncoderStateString[state]);
-
-       printf("testing FLAC__seekable_stream_encoder_get_stream_encoder_state()... ");
-       state_ = FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)state_, FLAC__StreamEncoderStateString[state_]);
-
-       printf("testing FLAC__seekable_stream_encoder_get_verify_decoder_state()... ");
-       dstate = FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]);
-
-       {
-               FLAC__uint64 absolute_sample;
-               unsigned frame_number;
-               unsigned channel;
-               unsigned sample;
-               FLAC__int32 expected;
-               FLAC__int32 got;
-
-               printf("testing FLAC__seekable_stream_encoder_get_verify_decoder_error_stats()... ");
-               FLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               printf("OK\n");
-       }
-
-       printf("testing FLAC__seekable_stream_encoder_get_verify()... ");
-       if(FLAC__seekable_stream_encoder_get_verify(encoder) != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_streamable_subset()... ");
-       if(FLAC__seekable_stream_encoder_get_streamable_subset(encoder) != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_do_mid_side_stereo()... ");
-       if(FLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_loose_mid_side_stereo()... ");
-       if(FLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_channels()... ");
-       if(FLAC__seekable_stream_encoder_get_channels(encoder) != streaminfo_.data.stream_info.channels) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, FLAC__seekable_stream_encoder_get_channels(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_bits_per_sample()... ");
-       if(FLAC__seekable_stream_encoder_get_bits_per_sample(encoder) != streaminfo_.data.stream_info.bits_per_sample) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, FLAC__seekable_stream_encoder_get_bits_per_sample(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_sample_rate()... ");
-       if(FLAC__seekable_stream_encoder_get_sample_rate(encoder) != streaminfo_.data.stream_info.sample_rate) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, FLAC__seekable_stream_encoder_get_sample_rate(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_blocksize()... ");
-       if(FLAC__seekable_stream_encoder_get_blocksize(encoder) != streaminfo_.data.stream_info.min_blocksize) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, FLAC__seekable_stream_encoder_get_blocksize(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_max_lpc_order()... ");
-       if(FLAC__seekable_stream_encoder_get_max_lpc_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, FLAC__seekable_stream_encoder_get_max_lpc_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_qlp_coeff_precision()... ");
-       (void)FLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder);
-       /* we asked the encoder to auto select this so we accept anything */
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search()... ");
-       if(FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_do_escape_coding()... ");
-       if(FLAC__seekable_stream_encoder_get_do_escape_coding(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_do_exhaustive_model_search()... ");
-       if(FLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_min_residual_partition_order()... ");
-       if(FLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, FLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_max_residual_partition_order()... ");
-       if(FLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, FLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_rice_parameter_search_dist()... ");
-       if(FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_get_total_samples_estimate()... ");
-       if(FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder) != streaminfo_.data.stream_info.total_samples) {
-               printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       printf("testing FLAC__seekable_stream_encoder_process()... ");
-       if(!FLAC__seekable_stream_encoder_process(encoder, (const FLAC__int32 * const *)samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_process_interleaved()... ");
-       if(!FLAC__seekable_stream_encoder_process_interleaved(encoder, samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_finish()... ");
-       FLAC__seekable_stream_encoder_finish(encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__seekable_stream_encoder_delete()... ");
-       FLAC__seekable_stream_encoder_delete(encoder);
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-static void file_encoder_progress_callback_(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
-{
-       (void)encoder, (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate, (void)client_data;
-}
-
-static FLAC__bool test_file_encoder()
-{
-       FLAC__FileEncoder *encoder;
-       FLAC__FileEncoderState state;
-       FLAC__SeekableStreamEncoderState state_;
-       FLAC__StreamEncoderState state__;
-       FLAC__StreamDecoderState dstate;
-       FLAC__int32 samples[1024];
-       FLAC__int32 *samples_array[1];
-       unsigned i;
-
-       samples_array[0] = samples;
-
-       printf("\n+++ libFLAC unit test: FLAC__FileEncoder\n\n");
-
-       printf("testing FLAC__file_encoder_new()... ");
-       encoder = FLAC__file_encoder_new();
-       if(0 == encoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_verify()... ");
-       if(!FLAC__file_encoder_set_verify(encoder, true))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_streamable_subset()... ");
-       if(!FLAC__file_encoder_set_streamable_subset(encoder, true))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_do_mid_side_stereo()... ");
-       if(!FLAC__file_encoder_set_do_mid_side_stereo(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_loose_mid_side_stereo()... ");
-       if(!FLAC__file_encoder_set_loose_mid_side_stereo(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_channels()... ");
-       if(!FLAC__file_encoder_set_channels(encoder, streaminfo_.data.stream_info.channels))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_bits_per_sample()... ");
-       if(!FLAC__file_encoder_set_bits_per_sample(encoder, streaminfo_.data.stream_info.bits_per_sample))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_sample_rate()... ");
-       if(!FLAC__file_encoder_set_sample_rate(encoder, streaminfo_.data.stream_info.sample_rate))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_blocksize()... ");
-       if(!FLAC__file_encoder_set_blocksize(encoder, streaminfo_.data.stream_info.min_blocksize))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_max_lpc_order()... ");
-       if(!FLAC__file_encoder_set_max_lpc_order(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_qlp_coeff_precision()... ");
-       if(!FLAC__file_encoder_set_qlp_coeff_precision(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_do_qlp_coeff_prec_search()... ");
-       if(!FLAC__file_encoder_set_do_qlp_coeff_prec_search(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_do_escape_coding()... ");
-       if(!FLAC__file_encoder_set_do_escape_coding(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_do_exhaustive_model_search()... ");
-       if(!FLAC__file_encoder_set_do_exhaustive_model_search(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_min_residual_partition_order()... ");
-       if(!FLAC__file_encoder_set_min_residual_partition_order(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_max_residual_partition_order()... ");
-       if(!FLAC__file_encoder_set_max_residual_partition_order(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_rice_parameter_search_dist()... ");
-       if(!FLAC__file_encoder_set_rice_parameter_search_dist(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_total_samples_estimate()... ");
-       if(!FLAC__file_encoder_set_total_samples_estimate(encoder, streaminfo_.data.stream_info.total_samples))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_metadata()... ");
-       if(!FLAC__file_encoder_set_metadata(encoder, metadata_sequence_, num_metadata_))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_filename()... ");
-       if(!FLAC__file_encoder_set_filename(encoder, flacfilename_))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_progress_callback()... ");
-       if(!FLAC__file_encoder_set_progress_callback(encoder, file_encoder_progress_callback_))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_set_client_data()... ");
-       if(!FLAC__file_encoder_set_client_data(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_init()... ");
-       if(FLAC__file_encoder_init(encoder) != FLAC__FILE_ENCODER_OK)
-               return die_f_(0, encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_state()... ");
-       state = FLAC__file_encoder_get_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)state, FLAC__FileEncoderStateString[state]);
-
-       printf("testing FLAC__file_encoder_get_seekable_stream_encoder_state()... ");
-       state_ = FLAC__file_encoder_get_seekable_stream_encoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)state_, FLAC__SeekableStreamEncoderStateString[state_]);
-
-       printf("testing FLAC__file_encoder_get_stream_encoder_state()... ");
-       state__ = FLAC__file_encoder_get_stream_encoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)state__, FLAC__StreamEncoderStateString[state__]);
-
-       printf("testing FLAC__file_encoder_get_verify_decoder_state()... ");
-       dstate = FLAC__file_encoder_get_verify_decoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]);
-
-       {
-               FLAC__uint64 absolute_sample;
-               unsigned frame_number;
-               unsigned channel;
-               unsigned sample;
-               FLAC__int32 expected;
-               FLAC__int32 got;
-
-               printf("testing FLAC__file_encoder_get_verify_decoder_error_stats()... ");
-               FLAC__file_encoder_get_verify_decoder_error_stats(encoder, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               printf("OK\n");
-       }
-
-       printf("testing FLAC__file_encoder_get_verify()... ");
-       if(FLAC__file_encoder_get_verify(encoder) != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_streamable_subset()... ");
-       if(FLAC__file_encoder_get_streamable_subset(encoder) != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_do_mid_side_stereo()... ");
-       if(FLAC__file_encoder_get_do_mid_side_stereo(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_loose_mid_side_stereo()... ");
-       if(FLAC__file_encoder_get_loose_mid_side_stereo(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_channels()... ");
-       if(FLAC__file_encoder_get_channels(encoder) != streaminfo_.data.stream_info.channels) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, FLAC__file_encoder_get_channels(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_bits_per_sample()... ");
-       if(FLAC__file_encoder_get_bits_per_sample(encoder) != streaminfo_.data.stream_info.bits_per_sample) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, FLAC__file_encoder_get_bits_per_sample(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_sample_rate()... ");
-       if(FLAC__file_encoder_get_sample_rate(encoder) != streaminfo_.data.stream_info.sample_rate) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, FLAC__file_encoder_get_sample_rate(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_blocksize()... ");
-       if(FLAC__file_encoder_get_blocksize(encoder) != streaminfo_.data.stream_info.min_blocksize) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, FLAC__file_encoder_get_blocksize(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_max_lpc_order()... ");
-       if(FLAC__file_encoder_get_max_lpc_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, FLAC__file_encoder_get_max_lpc_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_qlp_coeff_precision()... ");
-       (void)FLAC__file_encoder_get_qlp_coeff_precision(encoder);
-       /* we asked the encoder to auto select this so we accept anything */
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_do_qlp_coeff_prec_search()... ");
-       if(FLAC__file_encoder_get_do_qlp_coeff_prec_search(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_do_escape_coding()... ");
-       if(FLAC__file_encoder_get_do_escape_coding(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_do_exhaustive_model_search()... ");
-       if(FLAC__file_encoder_get_do_exhaustive_model_search(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_min_residual_partition_order()... ");
-       if(FLAC__file_encoder_get_min_residual_partition_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, FLAC__file_encoder_get_min_residual_partition_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_max_residual_partition_order()... ");
-       if(FLAC__file_encoder_get_max_residual_partition_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, FLAC__file_encoder_get_max_residual_partition_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_rice_parameter_search_dist()... ");
-       if(FLAC__file_encoder_get_rice_parameter_search_dist(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, FLAC__file_encoder_get_rice_parameter_search_dist(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_get_total_samples_estimate()... ");
-       if(FLAC__file_encoder_get_total_samples_estimate(encoder) != streaminfo_.data.stream_info.total_samples) {
-               printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, FLAC__file_encoder_get_total_samples_estimate(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       printf("testing FLAC__file_encoder_process()... ");
-       if(!FLAC__file_encoder_process(encoder, (const FLAC__int32 * const *)samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_process_interleaved()... ");
-       if(!FLAC__file_encoder_process_interleaved(encoder, samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_finish()... ");
-       FLAC__file_encoder_finish(encoder);
-       printf("OK\n");
-
-       printf("testing FLAC__file_encoder_delete()... ");
-       FLAC__file_encoder_delete(encoder);
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
 FLAC__bool test_encoders()
 {
        init_metadata_blocks_();
 
-       if(!test_stream_encoder())
+       if(!test_stream_encoder(LAYER_STREAM))
+               return false;
+
+       if(!test_stream_encoder(LAYER_SEEKABLE_STREAM))
                return false;
 
-       if(!test_seekable_stream_encoder())
+       if(!test_stream_encoder(LAYER_FILE))
                return false;
 
-       if(!test_file_encoder())
+       if(!test_stream_encoder(LAYER_FILENAME))
                return false;
 
        (void) grabbag__file_remove_file(flacfilename_);
diff --git a/src/test_libFLAC/file_utils.c b/src/test_libFLAC/file_utils.c
deleted file mode 100644 (file)
index 8baf9ea..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* test_libFLAC - Unit tester for libFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "file_utils.h"
-#include "FLAC/assert.h"
-#include "FLAC/stream_encoder.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h> /* for stat() */
-
-#ifdef min
-#undef min
-#endif
-#define min(a,b) ((a)<(b)?(a):(b))
-
-#ifdef FLAC__VALGRIND_TESTING
-static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
-       size_t ret = fwrite(ptr, size, nmemb, stream);
-       if(!ferror(stream))
-               fflush(stream);
-       return ret;
-}
-#else
-#define local__fwrite fwrite
-#endif
-
-typedef struct {
-       FILE *file;
-} encoder_client_struct;
-
-static FLAC__StreamEncoderWriteStatus encoder_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       encoder_client_struct *ecd = (encoder_client_struct*)client_data;
-
-       (void)encoder, (void)samples, (void)current_frame;
-
-       if(local__fwrite(buffer, 1, bytes, ecd->file) != bytes)
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
-       else
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-}
-
-static void encoder_metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       (void)encoder, (void)metadata, (void)client_data;
-}
-
-FLAC__bool file_utils__generate_flacfile(const char *output_filename, off_t *output_filesize, unsigned length, const FLAC__StreamMetadata *streaminfo, FLAC__StreamMetadata **metadata, unsigned num_metadata)
-{
-       FLAC__int32 samples[1024];
-       FLAC__StreamEncoder *encoder;
-       encoder_client_struct encoder_client_data;
-       unsigned i, n;
-
-       FLAC__ASSERT(0 != output_filename);
-       FLAC__ASSERT(0 != streaminfo);
-       FLAC__ASSERT(streaminfo->type == FLAC__METADATA_TYPE_STREAMINFO);
-       FLAC__ASSERT((streaminfo->is_last && num_metadata == 0) || (!streaminfo->is_last && num_metadata > 0));
-
-       if(0 == (encoder_client_data.file = fopen(output_filename, "wb")))
-               return false;
-
-       encoder = FLAC__stream_encoder_new();
-       if(0 == encoder) {
-               fclose(encoder_client_data.file);
-               return false;
-       }
-
-       FLAC__stream_encoder_set_verify(encoder, true);
-       FLAC__stream_encoder_set_streamable_subset(encoder, true);
-       FLAC__stream_encoder_set_do_mid_side_stereo(encoder, false);
-       FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, false);
-       FLAC__stream_encoder_set_channels(encoder, streaminfo->data.stream_info.channels);
-       FLAC__stream_encoder_set_bits_per_sample(encoder, streaminfo->data.stream_info.bits_per_sample);
-       FLAC__stream_encoder_set_sample_rate(encoder, streaminfo->data.stream_info.sample_rate);
-       FLAC__stream_encoder_set_blocksize(encoder, streaminfo->data.stream_info.min_blocksize);
-       FLAC__stream_encoder_set_max_lpc_order(encoder, 0);
-       FLAC__stream_encoder_set_qlp_coeff_precision(encoder, 0);
-       FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, false);
-       FLAC__stream_encoder_set_do_escape_coding(encoder, false);
-       FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, false);
-       FLAC__stream_encoder_set_min_residual_partition_order(encoder, 0);
-       FLAC__stream_encoder_set_max_residual_partition_order(encoder, 0);
-       FLAC__stream_encoder_set_rice_parameter_search_dist(encoder, 0);
-       FLAC__stream_encoder_set_total_samples_estimate(encoder, streaminfo->data.stream_info.total_samples);
-       FLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
-       FLAC__stream_encoder_set_write_callback(encoder, encoder_write_callback_);
-       FLAC__stream_encoder_set_metadata_callback(encoder, encoder_metadata_callback_);
-       FLAC__stream_encoder_set_client_data(encoder, &encoder_client_data);
-
-       if(FLAC__stream_encoder_init(encoder) != FLAC__STREAM_ENCODER_OK) {
-               fclose(encoder_client_data.file);
-               return false;
-       }
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       while(length > 0) {
-               n = min(length, sizeof(samples) / sizeof(FLAC__int32));
-
-               if(!FLAC__stream_encoder_process_interleaved(encoder, samples, n)) {
-                       fclose(encoder_client_data.file);
-                       return false;
-               }
-
-               length -= n;
-       }
-
-       FLAC__stream_encoder_finish(encoder);
-
-       fclose(encoder_client_data.file);
-
-       FLAC__stream_encoder_delete(encoder);
-
-       if(0 != output_filesize) {
-               struct stat filestats;
-
-               if(stat(output_filename, &filestats) != 0)
-                       return false;
-               else
-                       *output_filesize = filestats.st_size;
-       }
-
-       return true;
-}
index 55d85ef..85d8eb2 100644 (file)
 #include <unistd.h> /* for chown(), unlink() */
 #endif
 #include <sys/stat.h> /* for stat(), maybe chmod() */
-#include "file_utils.h"
-#include "metadata_utils.h"
 #include "FLAC/assert.h"
-#include "FLAC/file_decoder.h"
+#include "FLAC/stream_decoder.h"
 #include "FLAC/metadata.h"
 #include "share/grabbag.h"
+#include "test_libs_common/file_utils_flac.h"
+#include "test_libs_common/metadata_utils.h"
 
 
 /******************************************************************************
@@ -47,7 +47,7 @@
        to create a dummy FLAC file with a known set of initial metadata
        blocks, then keep a mirror locally of what we expect the metadata to be
        after each operation.  Then testing becomes a simple matter of running
-       a FLAC__FileDecoder over the dummy file after each operation, comparing
+       a FLAC__StreamDecoder over the dummy file after each operation, comparing
        the decoded metadata to what's in our local copy.  If there are any
        differences in the metadata, or the actual audio data is corrupted, we
        will catch it while decoding.
@@ -422,7 +422,7 @@ static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_p
 
 /* decoder callbacks for checking the file */
 
-static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
        (void)decoder, (void)buffer, (void)client_data;
 
@@ -438,7 +438,7 @@ static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDe
 }
 
 /* this version pays no attention to the metadata */
-static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+static void decoder_metadata_callback_null_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        (void)decoder, (void)metadata, (void)client_data;
 
@@ -449,7 +449,7 @@ static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, co
 }
 
 /* this version is used when we want to compare to our metadata copy */
-static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+static void decoder_metadata_callback_compare_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        decoder_client_struct *dcd = (decoder_client_struct*)client_data;
 
@@ -475,7 +475,7 @@ static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder,
        mc_our_block_number_++;
 }
 
-static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+static void decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
        decoder_client_struct *dcd = (decoder_client_struct*)client_data;
        (void)decoder;
@@ -559,9 +559,9 @@ static FLAC__bool generate_file_(FLAC__bool include_cuesheet)
        return true;
 }
 
-static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
+static FLAC__bool test_file_(const char *filename, FLAC__StreamDecoderMetadataCallback metadata_callback)
 {
-       FLAC__FileDecoder *decoder;
+       FLAC__StreamDecoder *decoder;
        decoder_client_struct decoder_client_data;
 
        FLAC__ASSERT(0 != filename);
@@ -573,29 +573,24 @@ static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCall
        printf("\ttesting '%s'... ", filename);
        fflush(stdout);
 
-       if(0 == (decoder = FLAC__file_decoder_new()))
+       if(0 == (decoder = FLAC__stream_decoder_new()))
                return die_("couldn't allocate decoder instance");
 
-       FLAC__file_decoder_set_md5_checking(decoder, true);
-       FLAC__file_decoder_set_filename(decoder, filename);
-       FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
-       FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
-       FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
-       FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
-       FLAC__file_decoder_set_metadata_respond_all(decoder);
-       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
-               FLAC__file_decoder_finish(decoder);
-               FLAC__file_decoder_delete(decoder);
+       FLAC__stream_decoder_set_md5_checking(decoder, true);
+       FLAC__stream_decoder_set_metadata_respond_all(decoder);
+       if(FLAC__stream_decoder_init_file(decoder, filename, decoder_write_callback_, metadata_callback, decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+               FLAC__stream_decoder_finish(decoder);
+               FLAC__stream_decoder_delete(decoder);
                return die_("initializing decoder\n");
        }
-       if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
-               FLAC__file_decoder_finish(decoder);
-               FLAC__file_decoder_delete(decoder);
+       if(!FLAC__stream_decoder_process_until_end_of_stream(decoder)) {
+               FLAC__stream_decoder_finish(decoder);
+               FLAC__stream_decoder_delete(decoder);
                return die_("decoding file\n");
        }
 
-       FLAC__file_decoder_finish(decoder);
-       FLAC__file_decoder_delete(decoder);
+       FLAC__stream_decoder_finish(decoder);
+       FLAC__stream_decoder_delete(decoder);
 
        if(decoder_client_data.error_occurred)
                return false;
index 2805d41..304df90 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "FLAC/assert.h"
 #include "FLAC/metadata.h"
-#include "metadata_utils.h"
+#include "test_libs_common/metadata_utils.h"
 #include <stdio.h>
 #include <stdlib.h> /* for malloc() */
 #include <string.h> /* for memcmp() */
@@ -467,7 +467,7 @@ static void cs_delete_(FLAC__StreamMetadata *block, unsigned pos)
 FLAC__bool test_metadata_object()
 {
        FLAC__StreamMetadata *block, *blockcopy, *vorbiscomment, *cuesheet;
-       FLAC__StreamMetadata_SeekPoint seekpoint_array[8];
+       FLAC__StreamMetadata_SeekPoint seekpoint_array[14];
        FLAC__StreamMetadata_VorbisComment_Entry entry;
        FLAC__StreamMetadata_CueSheet_Index index;
        FLAC__StreamMetadata_CueSheet_Track track;
@@ -879,6 +879,28 @@ FLAC__bool test_metadata_object()
        if(!check_seektable_(block, seekpoints, seekpoint_array))
                return false;
 
+       seekpoint_array[seekpoints++].sample_number = 0;
+       seekpoint_array[seekpoints++].sample_number = 10;
+       seekpoint_array[seekpoints++].sample_number = 20;
+       printf("testing FLAC__metadata_object_seekpoint_template_append_spaced_points_by_samples()... ");
+       if(!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(block, 10, 30)) {
+               printf("FAILED, returned false\n");
+               return false;
+       }
+       if(!check_seektable_(block, seekpoints, seekpoint_array))
+               return false;
+
+       seekpoint_array[seekpoints++].sample_number = 0;
+       seekpoint_array[seekpoints++].sample_number = 11;
+       seekpoint_array[seekpoints++].sample_number = 22;
+       printf("testing FLAC__metadata_object_seekpoint_template_append_spaced_points_by_samples()... ");
+       if(!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(block, 11, 30)) {
+               printf("FAILED, returned false\n");
+               return false;
+       }
+       if(!check_seektable_(block, seekpoints, seekpoint_array))
+               return false;
+
        printf("testing FLAC__metadata_object_delete()... ");
        FLAC__metadata_object_delete(block);
        printf("OK\n");
diff --git a/src/test_libFLAC/metadata_utils.c b/src/test_libFLAC/metadata_utils.c
deleted file mode 100644 (file)
index c866982..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-/* test_libFLAC - Unit tester for libFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * These are not tests, just utility functions used by the metadata tests
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "metadata_utils.h"
-#include "FLAC/metadata.h"
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for memcmp() */
-
-FLAC__bool mutils__compare_block_data_streaminfo(const FLAC__StreamMetadata_StreamInfo *block, const FLAC__StreamMetadata_StreamInfo *blockcopy)
-{
-       if(blockcopy->min_blocksize != block->min_blocksize) {
-               printf("FAILED, min_blocksize mismatch, expected %u, got %u\n", block->min_blocksize, blockcopy->min_blocksize);
-               return false;
-       }
-       if(blockcopy->max_blocksize != block->max_blocksize) {
-               printf("FAILED, max_blocksize mismatch, expected %u, got %u\n", block->max_blocksize, blockcopy->max_blocksize);
-               return false;
-       }
-       if(blockcopy->min_framesize != block->min_framesize) {
-               printf("FAILED, min_framesize mismatch, expected %u, got %u\n", block->min_framesize, blockcopy->min_framesize);
-               return false;
-       }
-       if(blockcopy->max_framesize != block->max_framesize) {
-               printf("FAILED, max_framesize mismatch, expected %u, got %u\n", block->max_framesize, blockcopy->max_framesize);
-               return false;
-       }
-       if(blockcopy->sample_rate != block->sample_rate) {
-               printf("FAILED, sample_rate mismatch, expected %u, got %u\n", block->sample_rate, blockcopy->sample_rate);
-               return false;
-       }
-       if(blockcopy->channels != block->channels) {
-               printf("FAILED, channels mismatch, expected %u, got %u\n", block->channels, blockcopy->channels);
-               return false;
-       }
-       if(blockcopy->bits_per_sample != block->bits_per_sample) {
-               printf("FAILED, bits_per_sample mismatch, expected %u, got %u\n", block->bits_per_sample, blockcopy->bits_per_sample);
-               return false;
-       }
-       if(blockcopy->total_samples != block->total_samples) {
-               printf("FAILED, total_samples mismatch, expected %llu, got %llu\n", block->total_samples, blockcopy->total_samples);
-               return false;
-       }
-       if(0 != memcmp(blockcopy->md5sum, block->md5sum, sizeof(block->md5sum))) {
-               printf("FAILED, md5sum mismatch, expected %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X, got %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
-                       (unsigned)block->md5sum[0],
-                       (unsigned)block->md5sum[1],
-                       (unsigned)block->md5sum[2],
-                       (unsigned)block->md5sum[3],
-                       (unsigned)block->md5sum[4],
-                       (unsigned)block->md5sum[5],
-                       (unsigned)block->md5sum[6],
-                       (unsigned)block->md5sum[7],
-                       (unsigned)block->md5sum[8],
-                       (unsigned)block->md5sum[9],
-                       (unsigned)block->md5sum[10],
-                       (unsigned)block->md5sum[11],
-                       (unsigned)block->md5sum[12],
-                       (unsigned)block->md5sum[13],
-                       (unsigned)block->md5sum[14],
-                       (unsigned)block->md5sum[15],
-                       (unsigned)blockcopy->md5sum[0],
-                       (unsigned)blockcopy->md5sum[1],
-                       (unsigned)blockcopy->md5sum[2],
-                       (unsigned)blockcopy->md5sum[3],
-                       (unsigned)blockcopy->md5sum[4],
-                       (unsigned)blockcopy->md5sum[5],
-                       (unsigned)blockcopy->md5sum[6],
-                       (unsigned)blockcopy->md5sum[7],
-                       (unsigned)blockcopy->md5sum[8],
-                       (unsigned)blockcopy->md5sum[9],
-                       (unsigned)blockcopy->md5sum[10],
-                       (unsigned)blockcopy->md5sum[11],
-                       (unsigned)blockcopy->md5sum[12],
-                       (unsigned)blockcopy->md5sum[13],
-                       (unsigned)blockcopy->md5sum[14],
-                       (unsigned)blockcopy->md5sum[15]
-               );
-               return false;
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_padding(const FLAC__StreamMetadata_Padding *block, const FLAC__StreamMetadata_Padding *blockcopy, unsigned block_length)
-{
-       /* we don't compare the padding guts */
-       (void)block, (void)blockcopy, (void)block_length;
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_application(const FLAC__StreamMetadata_Application *block, const FLAC__StreamMetadata_Application *blockcopy, unsigned block_length)
-{
-       if(block_length < sizeof(block->id)) {
-               printf("FAILED, bad block length = %u\n", block_length);
-               return false;
-       }
-       if(0 != memcmp(blockcopy->id, block->id, sizeof(block->id))) {
-               printf("FAILED, id mismatch, expected %02X%02X%02X%02X, got %02X%02X%02X%02X\n",
-                       (unsigned)block->id[0],
-                       (unsigned)block->id[1],
-                       (unsigned)block->id[2],
-                       (unsigned)block->id[3],
-                       (unsigned)blockcopy->id[0],
-                       (unsigned)blockcopy->id[1],
-                       (unsigned)blockcopy->id[2],
-                       (unsigned)blockcopy->id[3]
-               );
-               return false;
-       }
-       if(0 == block->data || 0 == blockcopy->data) {
-               if(block->data != blockcopy->data) {
-                       printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
-                       return false;
-               }
-               else if(block_length - sizeof(block->id) > 0) {
-                       printf("FAILED, data pointer is null but block length is not 0\n");
-                       return false;
-               }
-       }
-       else {
-               if(block_length - sizeof(block->id) == 0) {
-                       printf("FAILED, data pointer is not null but block length is 0\n");
-                       return false;
-               }
-               else if(0 != memcmp(blockcopy->data, block->data, block_length - sizeof(block->id))) {
-                       printf("FAILED, data mismatch\n");
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_seektable(const FLAC__StreamMetadata_SeekTable *block, const FLAC__StreamMetadata_SeekTable *blockcopy)
-{
-       unsigned i;
-       if(blockcopy->num_points != block->num_points) {
-               printf("FAILED, num_points mismatch, expected %u, got %u\n", block->num_points, blockcopy->num_points);
-               return false;
-       }
-       for(i = 0; i < block->num_points; i++) {
-               if(blockcopy->points[i].sample_number != block->points[i].sample_number) {
-                       printf("FAILED, points[%u].sample_number mismatch, expected %llu, got %llu\n", i, block->points[i].sample_number, blockcopy->points[i].sample_number);
-                       return false;
-               }
-               if(blockcopy->points[i].stream_offset != block->points[i].stream_offset) {
-                       printf("FAILED, points[%u].stream_offset mismatch, expected %llu, got %llu\n", i, block->points[i].stream_offset, blockcopy->points[i].stream_offset);
-                       return false;
-               }
-               if(blockcopy->points[i].frame_samples != block->points[i].frame_samples) {
-                       printf("FAILED, points[%u].frame_samples mismatch, expected %u, got %u\n", i, block->points[i].frame_samples, blockcopy->points[i].frame_samples);
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_vorbiscomment(const FLAC__StreamMetadata_VorbisComment *block, const FLAC__StreamMetadata_VorbisComment *blockcopy)
-{
-       unsigned i;
-       if(blockcopy->vendor_string.length != block->vendor_string.length) {
-               printf("FAILED, vendor_string.length mismatch, expected %u, got %u\n", block->vendor_string.length, blockcopy->vendor_string.length);
-               return false;
-       }
-       if(0 == block->vendor_string.entry || 0 == blockcopy->vendor_string.entry) {
-               if(block->vendor_string.entry != blockcopy->vendor_string.entry) {
-                       printf("FAILED, vendor_string.entry mismatch\n");
-                       return false;
-               }
-       }
-       else if(0 != memcmp(blockcopy->vendor_string.entry, block->vendor_string.entry, block->vendor_string.length)) {
-               printf("FAILED, vendor_string.entry mismatch\n");
-               return false;
-       }
-       if(blockcopy->num_comments != block->num_comments) {
-               printf("FAILED, num_comments mismatch, expected %u, got %u\n", block->num_comments, blockcopy->num_comments);
-               return false;
-       }
-       for(i = 0; i < block->num_comments; i++) {
-               if(blockcopy->comments[i].length != block->comments[i].length) {
-                       printf("FAILED, comments[%u].length mismatch, expected %u, got %u\n", i, block->comments[i].length, blockcopy->comments[i].length);
-                       return false;
-               }
-               if(0 == block->comments[i].entry || 0 == blockcopy->comments[i].entry) {
-                       if(block->comments[i].entry != blockcopy->comments[i].entry) {
-                               printf("FAILED, comments[%u].entry mismatch\n", i);
-                               return false;
-                       }
-               }
-               else {
-                       if(0 != memcmp(blockcopy->comments[i].entry, block->comments[i].entry, block->comments[i].length)) {
-                               printf("FAILED, comments[%u].entry mismatch\n", i);
-                               return false;
-                       }
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_cuesheet(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy)
-{
-       unsigned i, j;
-
-       if(0 != strcmp(blockcopy->media_catalog_number, block->media_catalog_number)) {
-               printf("FAILED, media_catalog_number mismatch, expected %s, got %s\n", block->media_catalog_number, blockcopy->media_catalog_number);
-               return false;
-       }
-       if(blockcopy->lead_in != block->lead_in) {
-               printf("FAILED, lead_in mismatch, expected %llu, got %llu\n", block->lead_in, blockcopy->lead_in);
-               return false;
-       }
-       if(blockcopy->is_cd != block->is_cd) {
-               printf("FAILED, is_cd mismatch, expected %u, got %u\n", (unsigned)block->is_cd, (unsigned)blockcopy->is_cd);
-               return false;
-       }
-       if(blockcopy->num_tracks != block->num_tracks) {
-               printf("FAILED, num_tracks mismatch, expected %u, got %u\n", block->num_tracks, blockcopy->num_tracks);
-               return false;
-       }
-       for(i = 0; i < block->num_tracks; i++) {
-               if(blockcopy->tracks[i].offset != block->tracks[i].offset) {
-                       printf("FAILED, tracks[%u].offset mismatch, expected %llu, got %llu\n", i, block->tracks[i].offset, blockcopy->tracks[i].offset);
-                       return false;
-               }
-               if(blockcopy->tracks[i].number != block->tracks[i].number) {
-                       printf("FAILED, tracks[%u].number mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].number, (unsigned)blockcopy->tracks[i].number);
-                       return false;
-               }
-               if(blockcopy->tracks[i].num_indices != block->tracks[i].num_indices) {
-                       printf("FAILED, tracks[%u].num_indices mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].num_indices, (unsigned)blockcopy->tracks[i].num_indices);
-                       return false;
-               }
-               /* num_indices == 0 means lead-out track so only the track offset and number are valid */
-               if(block->tracks[i].num_indices > 0) {
-                       if(0 != strcmp(blockcopy->tracks[i].isrc, block->tracks[i].isrc)) {
-                               printf("FAILED, tracks[%u].isrc mismatch, expected %s, got %s\n", i, block->tracks[i].isrc, blockcopy->tracks[i].isrc);
-                               return false;
-                       }
-                       if(blockcopy->tracks[i].type != block->tracks[i].type) {
-                               printf("FAILED, tracks[%u].type mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].type, (unsigned)blockcopy->tracks[i].type);
-                               return false;
-                       }
-                       if(blockcopy->tracks[i].pre_emphasis != block->tracks[i].pre_emphasis) {
-                               printf("FAILED, tracks[%u].pre_emphasis mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].pre_emphasis, (unsigned)blockcopy->tracks[i].pre_emphasis);
-                               return false;
-                       }
-                       if(0 == block->tracks[i].indices || 0 == blockcopy->tracks[i].indices) {
-                               if(block->tracks[i].indices != blockcopy->tracks[i].indices) {
-                                       printf("FAILED, tracks[%u].indices mismatch\n", i);
-                                       return false;
-                               }
-                       }
-                       else {
-                               for(j = 0; j < block->tracks[i].num_indices; j++) {
-                                       if(blockcopy->tracks[i].indices[j].offset != block->tracks[i].indices[j].offset) {
-                                               printf("FAILED, tracks[%u].indices[%u].offset mismatch, expected %llu, got %llu\n", i, j, block->tracks[i].indices[j].offset, blockcopy->tracks[i].indices[j].offset);
-                                               return false;
-                                       }
-                                       if(blockcopy->tracks[i].indices[j].number != block->tracks[i].indices[j].number) {
-                                               printf("FAILED, tracks[%u].indices[%u].number mismatch, expected %u, got %u\n", i, j, (unsigned)block->tracks[i].indices[j].number, (unsigned)blockcopy->tracks[i].indices[j].number);
-                                               return false;
-                                       }
-                               }
-                       }
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length)
-{
-       if(0 == block->data || 0 == blockcopy->data) {
-               if(block->data != blockcopy->data) {
-                       printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
-                       return false;
-               }
-               else if(block_length > 0) {
-                       printf("FAILED, data pointer is null but block length is not 0\n");
-                       return false;
-               }
-       }
-       else {
-               if(block_length == 0) {
-                       printf("FAILED, data pointer is not null but block length is 0\n");
-                       return false;
-               }
-               else if(0 != memcmp(blockcopy->data, block->data, block_length)) {
-                       printf("FAILED, data mismatch\n");
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy)
-{
-       if(blockcopy->type != block->type) {
-               printf("FAILED, type mismatch, expected %s, got %s\n", FLAC__MetadataTypeString[block->type], FLAC__MetadataTypeString[blockcopy->type]);
-               return false;
-       }
-       if(blockcopy->is_last != block->is_last) {
-               printf("FAILED, is_last mismatch, expected %u, got %u\n", (unsigned)block->is_last, (unsigned)blockcopy->is_last);
-               return false;
-       }
-       if(blockcopy->length != block->length) {
-               printf("FAILED, length mismatch, expected %u, got %u\n", block->length, blockcopy->length);
-               return false;
-       }
-       switch(block->type) {
-               case FLAC__METADATA_TYPE_STREAMINFO:
-                       return mutils__compare_block_data_streaminfo(&block->data.stream_info, &blockcopy->data.stream_info);
-               case FLAC__METADATA_TYPE_PADDING:
-                       return mutils__compare_block_data_padding(&block->data.padding, &blockcopy->data.padding, block->length);
-               case FLAC__METADATA_TYPE_APPLICATION:
-                       return mutils__compare_block_data_application(&block->data.application, &blockcopy->data.application, block->length);
-               case FLAC__METADATA_TYPE_SEEKTABLE:
-                       return mutils__compare_block_data_seektable(&block->data.seek_table, &blockcopy->data.seek_table);
-               case FLAC__METADATA_TYPE_VORBIS_COMMENT:
-                       return mutils__compare_block_data_vorbiscomment(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
-               case FLAC__METADATA_TYPE_CUESHEET:
-                       return mutils__compare_block_data_cuesheet(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
-               default:
-                       return mutils__compare_block_data_unknown(&block->data.unknown, &blockcopy->data.unknown, block->length);
-       }
-}
-static void *malloc_or_die_(size_t size)
-{
-       void *x = malloc(size);
-       if(0 == x) {
-               fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
-               exit(1);
-       }
-       return x;
-}
-
-static void *calloc_or_die_(size_t n, size_t size)
-{
-       void *x = calloc(n, size);
-       if(0 == x) {
-               fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)n * (unsigned)size);
-               exit(1);
-       }
-       return x;
-}
-
-void mutils__init_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-)
-{
-       /*
-               most of the actual numbers and data in the blocks don't matter,
-               we just want to make sure the decoder parses them correctly
-
-               remember, the metadata interface gets tested after the decoders,
-               so we do all the metadata manipulation here without it.
-       */
-
-       /* min/max_framesize and md5sum don't get written at first, so we have to leave them 0 */
-       streaminfo->is_last = false;
-       streaminfo->type = FLAC__METADATA_TYPE_STREAMINFO;
-       streaminfo->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
-       streaminfo->data.stream_info.min_blocksize = 576;
-       streaminfo->data.stream_info.max_blocksize = 576;
-       streaminfo->data.stream_info.min_framesize = 0;
-       streaminfo->data.stream_info.max_framesize = 0;
-       streaminfo->data.stream_info.sample_rate = 44100;
-       streaminfo->data.stream_info.channels = 1;
-       streaminfo->data.stream_info.bits_per_sample = 8;
-       streaminfo->data.stream_info.total_samples = 0;
-       memset(streaminfo->data.stream_info.md5sum, 0, 16);
-
-       padding->is_last = false;
-       padding->type = FLAC__METADATA_TYPE_PADDING;
-       padding->length = 1234;
-
-       seektable->is_last = false;
-       seektable->type = FLAC__METADATA_TYPE_SEEKTABLE;
-       seektable->data.seek_table.num_points = 2;
-       seektable->length = seektable->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
-       seektable->data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)malloc_or_die_(seektable->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint));
-       seektable->data.seek_table.points[0].sample_number = 0;
-       seektable->data.seek_table.points[0].stream_offset = 0;
-       seektable->data.seek_table.points[0].frame_samples = streaminfo->data.stream_info.min_blocksize;
-       seektable->data.seek_table.points[1].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
-       seektable->data.seek_table.points[1].stream_offset = 1000;
-       seektable->data.seek_table.points[1].frame_samples = streaminfo->data.stream_info.min_blocksize;
-
-       application1->is_last = false;
-       application1->type = FLAC__METADATA_TYPE_APPLICATION;
-       application1->length = 8;
-       memcpy(application1->data.application.id, "\xfe\xdc\xba\x98", 4);
-       application1->data.application.data = (FLAC__byte*)malloc_or_die_(4);
-       memcpy(application1->data.application.data, "\xf0\xe1\xd2\xc3", 4);
-
-       application2->is_last = false;
-       application2->type = FLAC__METADATA_TYPE_APPLICATION;
-       application2->length = 4;
-       memcpy(application2->data.application.id, "\x76\x54\x32\x10", 4);
-       application2->data.application.data = 0;
-
-       {
-               const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
-               vorbiscomment->is_last = false;
-               vorbiscomment->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
-               vorbiscomment->length = (4 + vendor_string_length) + 4 + (4 + 5) + (4 + 0);
-               vorbiscomment->data.vorbis_comment.vendor_string.length = vendor_string_length;
-               vorbiscomment->data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
-               memcpy(vorbiscomment->data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
-               vorbiscomment->data.vorbis_comment.num_comments = 2;
-               vorbiscomment->data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc_or_die_(vorbiscomment->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
-               vorbiscomment->data.vorbis_comment.comments[0].length = 5;
-               vorbiscomment->data.vorbis_comment.comments[0].entry = (FLAC__byte*)malloc_or_die_(5+1);
-               memcpy(vorbiscomment->data.vorbis_comment.comments[0].entry, "ab=cd", 5+1);
-               vorbiscomment->data.vorbis_comment.comments[1].length = 0;
-               vorbiscomment->data.vorbis_comment.comments[1].entry = 0;
-       }
-
-       cuesheet->is_last = false;
-       cuesheet->type = FLAC__METADATA_TYPE_CUESHEET;
-       cuesheet->length =
-               /* cuesheet guts */
-               (
-                       FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
-               ) / 8 +
-               /* 2 tracks */
-               3 * (
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
-               ) / 8 +
-               /* 3 index points */
-               3 * (
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
-               ) / 8
-       ;
-       memset(cuesheet->data.cue_sheet.media_catalog_number, 0, sizeof(cuesheet->data.cue_sheet.media_catalog_number));
-       cuesheet->data.cue_sheet.media_catalog_number[0] = 'j';
-       cuesheet->data.cue_sheet.media_catalog_number[1] = 'C';
-       cuesheet->data.cue_sheet.lead_in = 2 * 44100;
-       cuesheet->data.cue_sheet.is_cd = true;
-       cuesheet->data.cue_sheet.num_tracks = 3;
-       cuesheet->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc_or_die_(cuesheet->data.cue_sheet.num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));
-       cuesheet->data.cue_sheet.tracks[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[0].number = 1;
-       memcpy(cuesheet->data.cue_sheet.tracks[0].isrc, "ACBDE1234567", sizeof(cuesheet->data.cue_sheet.tracks[0].isrc));
-       cuesheet->data.cue_sheet.tracks[0].type = 0;
-       cuesheet->data.cue_sheet.tracks[0].pre_emphasis = 1;
-       cuesheet->data.cue_sheet.tracks[0].num_indices = 2;
-       cuesheet->data.cue_sheet.tracks[0].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet->data.cue_sheet.tracks[0].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
-       cuesheet->data.cue_sheet.tracks[0].indices[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[0].indices[0].number = 0;
-       cuesheet->data.cue_sheet.tracks[0].indices[1].offset = 123 * 588;
-       cuesheet->data.cue_sheet.tracks[0].indices[1].number = 1;
-       cuesheet->data.cue_sheet.tracks[1].offset = 1234 * 588;
-       cuesheet->data.cue_sheet.tracks[1].number = 2;
-       memcpy(cuesheet->data.cue_sheet.tracks[1].isrc, "ACBDE7654321", sizeof(cuesheet->data.cue_sheet.tracks[1].isrc));
-       cuesheet->data.cue_sheet.tracks[1].type = 1;
-       cuesheet->data.cue_sheet.tracks[1].pre_emphasis = 0;
-       cuesheet->data.cue_sheet.tracks[1].num_indices = 1;
-       cuesheet->data.cue_sheet.tracks[1].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet->data.cue_sheet.tracks[1].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
-       cuesheet->data.cue_sheet.tracks[1].indices[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[1].indices[0].number = 1;
-       cuesheet->data.cue_sheet.tracks[2].offset = 12345 * 588;
-       cuesheet->data.cue_sheet.tracks[2].number = 170;
-       cuesheet->data.cue_sheet.tracks[2].num_indices = 0;
-
-       unknown->is_last = true;
-       unknown->type = 127;
-       unknown->length = 8;
-       unknown->data.unknown.data = (FLAC__byte*)malloc_or_die_(unknown->length);
-       memcpy(unknown->data.unknown.data, "\xfe\xdc\xba\x98\xf0\xe1\xd2\xc3", unknown->length);
-}
-
-void mutils__free_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-)
-{
-       (void)streaminfo, (void)padding, (void)application2;
-       free(seektable->data.seek_table.points);
-       free(application1->data.application.data);
-       free(vorbiscomment->data.vorbis_comment.vendor_string.entry);
-       free(vorbiscomment->data.vorbis_comment.comments[0].entry);
-       free(vorbiscomment->data.vorbis_comment.comments);
-       free(cuesheet->data.cue_sheet.tracks[0].indices);
-       free(cuesheet->data.cue_sheet.tracks[1].indices);
-       free(cuesheet->data.cue_sheet.tracks);
-       free(unknown->data.unknown.data);
-}
diff --git a/src/test_libFLAC/metadata_utils.h b/src/test_libFLAC/metadata_utils.h
deleted file mode 100644 (file)
index 3d7af19..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* test_libFLAC - Unit tester for libFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef FLAC__TEST_LIBFLAC_METADATA_H
-#define FLAC__TEST_LIBFLAC_METADATA_H
-
-/*
- * These are not tests, just utility functions used by the metadata tests
- */
-
-#include "FLAC/format.h"
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for memcmp() */
-
-FLAC__bool mutils__compare_block_data_streaminfo(const FLAC__StreamMetadata_StreamInfo *block, const FLAC__StreamMetadata_StreamInfo *blockcopy);
-
-FLAC__bool mutils__compare_block_data_padding(const FLAC__StreamMetadata_Padding *block, const FLAC__StreamMetadata_Padding *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block_data_application(const FLAC__StreamMetadata_Application *block, const FLAC__StreamMetadata_Application *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block_data_seektable(const FLAC__StreamMetadata_SeekTable *block, const FLAC__StreamMetadata_SeekTable *blockcopy);
-
-FLAC__bool mutils__compare_block_data_vorbiscomment(const FLAC__StreamMetadata_VorbisComment *block, const FLAC__StreamMetadata_VorbisComment *blockcopy);
-
-FLAC__bool mutils__compare_block_data_cuesheet(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy);
-
-FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy);
-
-void mutils__init_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-);
-
-void mutils__free_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-);
-
-#endif
index 18fb79d..0320acd 100644 (file)
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
-# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\libFLAC_static.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\test_libs_common_static.lib ..\..\obj\release\lib\libFLAC_static.lib /nologo /subsystem:console /machine:I386\r
 \r
 !ELSEIF  "$(CFG)" == "test_libFLAC - Win32 Debug"\r
 \r
@@ -76,7 +76,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\libFLAC_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\test_libs_common_static.lib ..\..\obj\debug\lib\libFLAC_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
 \r
 !ENDIF \r
 \r
@@ -101,10 +101,6 @@ SOURCE=.\encoders.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\file_utils.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\format.c\r
 # End Source File\r
 # Begin Source File\r
@@ -123,10 +119,6 @@ SOURCE=.\metadata_manip.c
 \r
 SOURCE=.\metadata_object.c\r
 # End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\metadata_utils.c\r
-# End Source File\r
 # End Group\r
 # Begin Group "Header Files"\r
 \r
@@ -145,20 +137,12 @@ SOURCE=.\encoders.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\file_utils.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\format.h\r
 # End Source File\r
 # Begin Source File\r
 \r
 SOURCE=.\metadata.h\r
 # End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\metadata_utils.h\r
-# End Source File\r
 # End Group\r
 # End Target\r
 # End Project\r
index 4244a1f..f626b35 100644 (file)
@@ -17,7 +17,6 @@
 
 EXTRA_DIST = \
        Makefile.lite \
-       README \
        test_libOggFLAC++.dsp
 
 AM_CFLAGS = @OGG_CFLAGS@
@@ -26,6 +25,7 @@ noinst_PROGRAMS = test_libOggFLAC++
 test_libOggFLAC___LDADD = \
        $(top_builddir)/src/share/grabbag/libgrabbag.la \
        $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+       $(top_builddir)/src/test_libs_common/libtest_libs_common.la \
        $(top_builddir)/src/libOggFLAC++/libOggFLAC++.la \
        $(top_builddir)/src/libOggFLAC/libOggFLAC.la \
        $(top_builddir)/src/libFLAC/libFLAC.la \
@@ -34,10 +34,6 @@ test_libOggFLAC___LDADD = \
 test_libOggFLAC___SOURCES = \
        decoders.cpp \
        encoders.cpp \
-       file_utils.c \
        main.cpp \
-       metadata_utils.c \
        decoders.h \
-       encoders.h \
-       file_utils.h \
-       metadata_utils.h
+       encoders.h
index c546161..a8c4183 100644 (file)
@@ -27,14 +27,11 @@ PROGRAM_NAME = test_libOggFLAC++
 INCLUDES = -I$(topdir)/include
 
 ifeq ($(DARWIN_BUILD),yes)
-EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libreplaygain_analysis.a $(libdir)/libOggFLAC++.a $(libdir)/libOggFLAC.a $(libdir)/libFLAC.a $(OGG_LIB_DIR)/libogg.a -lm
+EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libreplaygain_analysis.a $(libdir)/libtest_libs_common.a $(libdir)/libOggFLAC++.a $(libdir)/libOggFLAC.a $(libdir)/libFLAC.a $(OGG_LIB_DIR)/libogg.a -lm
 else
-LIBS = -lgrabbag -lreplaygain_analysis -lOggFLAC++ -lOggFLAC -lFLAC -L$(OGG_LIB_DIR) -logg -lm
+LIBS = -lgrabbag -lreplaygain_analysis -ltest_libs_common -lOggFLAC++ -lOggFLAC -lFLAC -L$(OGG_LIB_DIR) -logg -lm
 endif
 
-SRCS_C = \
-       file_utils.c \
-       metadata_utils.c
 SRCS_CPP = \
        decoders.cpp \
        encoders.cpp \
diff --git a/src/test_libOggFLAC++/README b/src/test_libOggFLAC++/README
deleted file mode 100644 (file)
index 44ec3f9..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-NOTE: the following files are copied from the ../test_libOggFLAC directory:
-
-       file_utils.c
-       file_utils.h
-
-NOTE: the following files are copied from the ../test_libFLAC++ directory:
-
-       metadata_utils.c
-       metadata_utils.h
-
-It's too much of a pain to make a convenience library for these and CVS
-can't do soft links, so we put up with having two copies of these sources.
index 0222cd9..0776d0b 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #define ftello ftell
 #endif
 #include "decoders.h"
-extern "C" {
-#include "file_utils.h"
-#include "metadata_utils.h"
-}
 #include "FLAC/assert.h"
 #include "FLAC/metadata.h" // for ::FLAC__metadata_object_is_equal()
 #include "OggFLAC++/decoder.h"
 #include "share/grabbag.h"
+extern "C" {
+#include "test_libs_common/file_utils_oggflac.h"
+#include "test_libs_common/metadata_utils.h"
+}
 
 #ifdef _MSC_VER
 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
 #pragma warning ( disable : 4800 )
 #endif
 
+typedef enum {
+       LAYER_STREAM = 0, /* FLAC__stream_decoder_init_stream() without seeking */
+       LAYER_SEEKABLE_STREAM, /* FLAC__stream_decoder_init_stream() with seeking */
+       LAYER_FILE, /* FLAC__stream_decoder_init_FILE() */
+       LAYER_FILENAME /* FLAC__stream_decoder_init_file() */
+} Layer;
+
+static const char * const LayerString[] = {
+       "Stream",
+       "Seekable Stream",
+       "FILE*",
+       "Filename"
+};
+
 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
 static ::FLAC__StreamMetadata *expected_metadata_sequence_[8];
 static unsigned num_expected_;
-static const char *oggflacfilename_ = "metadata.ogg";
-static off_t oggflacfilesize_;
+static const char *flacfilename_ = "metadata.ogg";
+static off_t flacfilesize_;
 
 static bool die_(const char *msg)
 {
@@ -52,6 +70,24 @@ static bool die_(const char *msg)
        return false;
 }
 
+static FLAC__bool die_s_(const char *msg, const OggFLAC::Decoder::Stream *decoder)
+{
+       OggFLAC::Decoder::Stream::State state = decoder->get_state();
+
+       if(msg)
+               printf("FAILED, %s", msg);
+       else
+               printf("FAILED");
+
+       printf(", 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_ = decoder->get_FLAC_stream_decoder_state();
+               printf("      FLAC stream decoder state = %u (%s)\n", (unsigned)((::FLAC::Decoder::Stream::State)state_), state_.as_cstring());
+       }
+
+       return false;
+}
+
 static void init_metadata_blocks_()
 {
        mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
@@ -76,7 +112,7 @@ static bool generate_file_()
        expected_metadata_sequence_[num_expected_++] = &unknown_;
        /* WATCHOUT: the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
 
-       if(!file_utils__generate_oggflacfile(oggflacfilename_, &oggflacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
+       if(!file_utils__generate_oggflacfile(flacfilename_, &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
                return die_("creating the encoded file");
 
        return true;
@@ -85,43 +121,17 @@ static bool generate_file_()
 
 class DecoderCommon {
 public:
-       FILE *file_;
+       Layer layer_;
        unsigned current_metadata_number_;
        bool ignore_errors_;
        bool error_occurred_;
 
-       DecoderCommon(): file_(0), current_metadata_number_(0), ignore_errors_(false), error_occurred_(false) { }
-       ::FLAC__StreamDecoderReadStatus common_read_callback_(FLAC__byte buffer[], unsigned *bytes);
+       DecoderCommon(Layer layer): layer_(layer), current_metadata_number_(0), ignore_errors_(false), error_occurred_(false) { }
        ::FLAC__StreamDecoderWriteStatus common_write_callback_(const ::FLAC__Frame *frame);
        void common_metadata_callback_(const ::FLAC__StreamMetadata *metadata);
        void common_error_callback_(::FLAC__StreamDecoderErrorStatus status);
 };
 
-::FLAC__StreamDecoderReadStatus DecoderCommon::common_read_callback_(FLAC__byte buffer[], unsigned *bytes)
-{
-       if(error_occurred_)
-               return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT;
-
-       if(feof(file_)) {
-               *bytes = 0;
-               return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-       }
-       else if(*bytes > 0) {
-               *bytes = ::fread(buffer, 1, *bytes, file_);
-               if(*bytes == 0) {
-                       if(feof(file_))
-                               return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-                       else
-                               return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-               }
-               else {
-                       return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-               }
-       }
-       else
-               return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
-}
-
 ::FLAC__StreamDecoderWriteStatus DecoderCommon::common_write_callback_(const ::FLAC__Frame *frame)
 {
        if(error_occurred_)
@@ -169,23 +179,107 @@ void DecoderCommon::common_error_callback_(::FLAC__StreamDecoderErrorStatus stat
 
 class StreamDecoder : public OggFLAC::Decoder::Stream, public DecoderCommon {
 public:
-       StreamDecoder(): OggFLAC::Decoder::Stream(), DecoderCommon() { }
+       FILE *file_;
+
+       StreamDecoder(Layer layer): OggFLAC::Decoder::Stream(), DecoderCommon(layer), file_(0) { }
        ~StreamDecoder() { }
 
        // from OggFLAC::Decoder::Stream
        ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
+       ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
+       ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
+       ::FLAC__StreamDecoderLengthStatus 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);
        void error_callback(::FLAC__StreamDecoderErrorStatus status);
 
-       bool die(const char *msg = 0) const;
-
        bool test_respond();
 };
 
 ::FLAC__StreamDecoderReadStatus StreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
 {
-       return common_read_callback_(buffer, bytes);
+       const unsigned requested_bytes = *bytes;
+
+       if(error_occurred_)
+               return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+
+       if(feof(file_)) {
+               *bytes = 0;
+               return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+       }
+       else if(requested_bytes > 0) {
+               *bytes = ::fread(buffer, 1, requested_bytes, file_);
+               if(*bytes == 0) {
+                       if(feof(file_))
+                               return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+                       else
+                               return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+               }
+               else {
+                       return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+               }
+       }
+       else
+               return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
+}
+
+::FLAC__StreamDecoderSeekStatus StreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset)
+{
+       if(layer_ == LAYER_STREAM)
+               return ::FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+
+       if(error_occurred_)
+               return ::FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+
+       if(fseeko(file_, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
+               error_occurred_ = true;
+               return ::FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+       }
+
+       return ::FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+::FLAC__StreamDecoderTellStatus StreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
+{
+       if(layer_ == LAYER_STREAM)
+               return ::FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
+
+       if(error_occurred_)
+               return ::FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+
+       off_t offset = ftello(file_);
+       *absolute_byte_offset = (FLAC__uint64)offset;
+
+       if(offset < 0) {
+               error_occurred_ = true;
+               return ::FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+       }
+
+       return ::FLAC__STREAM_DECODER_TELL_STATUS_OK;
+}
+
+::FLAC__StreamDecoderLengthStatus StreamDecoder::length_callback(FLAC__uint64 *stream_length)
+{
+       if(layer_ == LAYER_STREAM)
+               return ::FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+
+       if(error_occurred_)
+               return ::FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+
+       *stream_length = (FLAC__uint64)flacfilesize_;
+       return ::FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+}
+
+bool StreamDecoder::eof_callback()
+{
+       if(layer_ == LAYER_STREAM)
+               return false;
+
+       if(error_occurred_)
+               return true;
+
+       return (bool)feof(file_);
 }
 
 ::FLAC__StreamDecoderWriteStatus StreamDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
@@ -205,25 +299,16 @@ void StreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
        common_error_callback_(status);
 }
 
-bool StreamDecoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__StreamDecoderState)state), state.as_cstring());
-
-       return false;
-}
-
 bool StreamDecoder::test_respond()
 {
+       if(!set_md5_checking(true)) {
+               printf("FAILED at set_md5_checking(), returned false\n");
+               return false;
+       }
+
        printf("testing init()... ");
-       if(init() != ::OggFLAC__STREAM_DECODER_OK)
-               return die();
+       if(init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+               return die_s_(0, this);
        printf("OK\n");
 
        current_metadata_number_ = 0;
@@ -248,17 +333,106 @@ bool StreamDecoder::test_respond()
        return true;
 }
 
-static bool test_stream_decoder()
+class FileDecoder : public OggFLAC::Decoder::File, public DecoderCommon {
+public:
+       FileDecoder(Layer layer): OggFLAC::Decoder::File(), DecoderCommon(layer) { }
+       ~FileDecoder() { }
+
+       // from OggFLAC::Decoder::Stream
+       ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
+       void metadata_callback(const ::FLAC__StreamMetadata *metadata);
+       void error_callback(::FLAC__StreamDecoderErrorStatus status);
+
+       bool test_respond();
+};
+
+::FLAC__StreamDecoderWriteStatus FileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
+{
+       (void)buffer;
+       return common_write_callback_(frame);
+}
+
+void FileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
+{
+       common_metadata_callback_(metadata);
+}
+
+void FileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
+{
+       common_error_callback_(status);
+}
+
+bool FileDecoder::test_respond()
+{
+       if(!set_md5_checking(true)) {
+               printf("FAILED at set_md5_checking(), returned false\n");
+               return false;
+       }
+
+       switch(layer_) {
+               case LAYER_FILE:
+                       {
+                               printf("opening Ogg FLAC file... ");
+                               FILE *file = ::fopen(flacfilename_, "rb");
+                               if(0 == file) {
+                                       printf("ERROR (%s)\n", strerror(errno));
+                                       return false;
+                               }
+                               printf("OK\n");
+
+                               printf("testing init()... ");
+                               if(init(file) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                                       return die_s_(0, this);
+                       }
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing init()... ");
+                       if(init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, this);
+                       break;
+               default:
+                       die_("internal error 001");
+                       return false;
+       }
+       printf("OK\n");
+
+       current_metadata_number_ = 0;
+
+       printf("testing process_until_end_of_stream()... ");
+       if(!process_until_end_of_stream()) {
+               State state = get_state();
+               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::OggFLAC__StreamDecoderState)state), state.as_cstring());
+               return false;
+       }
+       printf("OK\n");
+
+       printf("testing finish()... ");
+       finish();
+       printf("OK\n");
+
+       return true;
+}
+
+static OggFLAC::Decoder::Stream *new_by_layer(Layer layer)
+{
+       if(layer < LAYER_FILE)
+               return new StreamDecoder(layer);
+       else
+               return new FileDecoder(layer);
+}
+
+static bool test_stream_decoder(Layer layer)
 {
-       StreamDecoder *decoder;
+       OggFLAC::Decoder::Stream *decoder;
+       bool expect;
 
-       printf("\n+++ libOggFLAC++ unit test: OggFLAC::Decoder::Stream\n\n");
+       printf("\n+++ libOggFLAC++ unit test: OggFLAC::Decoder::%s (layer: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer]);
 
        //
        // test new -> delete
        //
        printf("allocating decoder instance... ");
-       decoder = new StreamDecoder();
+       decoder = new_by_layer(layer);
        if(0 == decoder) {
                printf("FAILED, new returned NULL\n");
                return false;
@@ -280,7 +454,7 @@ static bool test_stream_decoder()
        // test new -> init -> delete
        //
        printf("allocating decoder instance... ");
-       decoder = new StreamDecoder();
+       decoder = new_by_layer(layer);
        if(0 == decoder) {
                printf("FAILED, new returned NULL\n");
                return false;
@@ -295,8 +469,25 @@ static bool test_stream_decoder()
        printf("OK\n");
 
        printf("testing init()... ");
-       if(decoder->init() != ::OggFLAC__STREAM_DECODER_OK)
-               return decoder->die();
+       switch(layer) {
+               case LAYER_STREAM:
+               case LAYER_SEEKABLE_STREAM:
+                       dynamic_cast<StreamDecoder*>(decoder)->file_ = stdin;
+                       if(decoder->init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILE:
+                       if(dynamic_cast<OggFLAC::Decoder::File*>(decoder)->init(stdin) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILENAME:
+                       if(dynamic_cast<OggFLAC::Decoder::File*>(decoder)->init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               default:
+                       die_("internal error 006");
+                       return false;
+       }
        printf("OK\n");
 
        printf("freeing decoder instance... ");
@@ -310,7 +501,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &streaminfo_;
 
        printf("allocating decoder instance... ");
-       decoder = new StreamDecoder();
+       decoder = new_by_layer(layer);
        if(0 == decoder) {
                printf("FAILED, new returned NULL\n");
                return false;
@@ -326,12 +517,53 @@ static bool test_stream_decoder()
 
        printf("testing set_serial_number()... ");
        if(!decoder->set_serial_number(file_utils__serial_number))
-               return decoder->die("returned false");
+               return die_s_("returned false", decoder);
        printf("OK\n");
 
-       printf("testing init()... ");
-       if(decoder->init() != ::OggFLAC__STREAM_DECODER_OK)
-               return decoder->die();
+       if(!decoder->set_md5_checking(true)) {
+               printf("FAILED at set_md5_checking(), returned false\n");
+               return false;
+       }
+
+       switch(layer) {
+               case LAYER_STREAM:
+               case LAYER_SEEKABLE_STREAM:
+                       printf("opening Ogg FLAC file... ");
+                       dynamic_cast<StreamDecoder*>(decoder)->file_ = ::fopen(flacfilename_, "rb");
+                       if(0 == dynamic_cast<StreamDecoder*>(decoder)->file_) {
+                               printf("ERROR (%s)\n", strerror(errno));
+                               return false;
+                       }
+                       printf("OK\n");
+
+                       printf("testing init()... ");
+                       if(decoder->init() != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILE:
+                       {
+                               printf("opening Ogg FLAC file... ");
+                               FILE *file = ::fopen(flacfilename_, "rb");
+                               if(0 == file) {
+                                       printf("ERROR (%s)\n", strerror(errno));
+                                       return false;
+                               }
+                               printf("OK\n");
+
+                               printf("testing init()... ");
+                               if(dynamic_cast<OggFLAC::Decoder::File*>(decoder)->init(file) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                                       return die_s_(0, decoder);
+                       }
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing init()... ");
+                       if(dynamic_cast<OggFLAC::Decoder::File*>(decoder)->init(flacfilename_) != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               default:
+                       die_("internal error 009");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing get_state()... ");
@@ -342,43 +574,61 @@ static bool test_stream_decoder()
        FLAC::Decoder::Stream::State state_ = decoder->get_FLAC_stream_decoder_state();
        printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state_), state_.as_cstring());
 
-       decoder->current_metadata_number_ = 0;
-       decoder->ignore_errors_ = false;
-       decoder->error_occurred_ = false;
+       dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
+       dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
+       dynamic_cast<DecoderCommon*>(decoder)->error_occurred_ = false;
 
-       printf("opening Ogg FLAC file... ");
-       decoder->file_ = ::fopen(oggflacfilename_, "rb");
-       if(0 == decoder->file_) {
-               printf("ERROR (%s)\n", strerror(errno));
+       printf("testing get_md5_checking()... ");
+       if(!decoder->get_md5_checking()) {
+               printf("FAILED, returned false, expected true\n");
                return false;
        }
        printf("OK\n");
 
        printf("testing process_until_end_of_metadata()... ");
        if(!decoder->process_until_end_of_metadata())
-               return decoder->die("returned false");
+               return die_s_("returned false", decoder);
        printf("OK\n");
 
        printf("testing process_single()... ");
        if(!decoder->process_single())
-               return decoder->die("returned false");
+               return die_s_("returned false", decoder);
        printf("OK\n");
 
-       printf("testing flush()... ");
-       if(!decoder->flush())
-               return decoder->die("returned false");
+       printf("testing skip_single_frame()... ");
+       if(!decoder->skip_single_frame())
+               return die_s_("returned false", decoder);
        printf("OK\n");
 
-       decoder->ignore_errors_ = true;
-       printf("testing process_single()... ");
-       if(!decoder->process_single())
-               return decoder->die("returned false");
+       if(layer < LAYER_FILE) {
+               printf("testing flush()... ");
+               if(!decoder->flush())
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+
+               dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = true;
+               printf("testing process_single()... ");
+               if(!decoder->process_single())
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+               dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
+       }
+
+       expect = (layer != LAYER_STREAM);
+       printf("testing seek_absolute()... ");
+       if(decoder->seek_absolute(0) != expect)
+               return die_s_(expect? "returned false" : "returned true", decoder);
        printf("OK\n");
-       decoder->ignore_errors_ = false;
 
        printf("testing process_until_end_of_stream()... ");
        if(!decoder->process_until_end_of_stream())
-               return decoder->die("returned false");
+               return die_s_("returned false", decoder);
+       printf("OK\n");
+
+       expect = (layer != LAYER_STREAM);
+       printf("testing seek_absolute()... ");
+       if(decoder->seek_absolute(0) != expect)
+               return die_s_(expect? "returned false" : "returned true", decoder);
        printf("OK\n");
 
        printf("testing get_channels()... ");
@@ -415,7 +665,9 @@ static bool test_stream_decoder()
        {
                unsigned blocksize = decoder->get_blocksize();
                /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
+               printf("returned %u... %s\n", blocksize, blocksize>0? "OK" : "FAILED");
+               if(blocksize == 0)
+                       return false;
        }
 
        printf("testing get_channel_assignment()... ");
@@ -424,24 +676,29 @@ static bool test_stream_decoder()
                printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
        }
 
-       printf("testing reset()... ");
-       if(!decoder->reset())
-               return decoder->die("returned false");
-       printf("OK\n");
+       if(layer < LAYER_FILE) {
+               printf("testing reset()... ");
+               if(!decoder->reset())
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+
+               if(layer == LAYER_STREAM) {
+                       /* after a reset() we have to rewind the input ourselves */
+                       printf("rewinding input... ");
+                       if(fseeko(dynamic_cast<StreamDecoder*>(decoder)->file_, 0, SEEK_SET) < 0) {
+                               printf("FAILED, errno = %d\n", errno);
+                               return false;
+                       }
+                       printf("OK\n");
+               }
 
-       decoder->current_metadata_number_ = 0;
+               dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
 
-       printf("rewinding input... ");
-       if(fseeko(decoder->file_, 0, SEEK_SET) < 0) {
-               printf("FAILED, errno = %d\n", errno);
-               return false;
+               printf("testing process_until_end_of_stream()... ");
+               if(!decoder->process_until_end_of_stream())
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
        }
-       printf("OK\n");
-
-       printf("testing process_until_end_of_stream()... ");
-       if(!decoder->process_until_end_of_stream())
-               return decoder->die("returned false");
-       printf("OK\n");
 
        printf("testing finish()... ");
        decoder->finish();
@@ -468,7 +725,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -484,7 +741,7 @@ static bool test_stream_decoder()
 
        num_expected_ = 0;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -514,7 +771,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -543,7 +800,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -573,7 +830,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -609,7 +866,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -633,7 +890,7 @@ static bool test_stream_decoder()
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -658,7 +915,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &application1_;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -682,7 +939,7 @@ static bool test_stream_decoder()
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &application1_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -714,7 +971,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &application1_;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -751,7 +1008,7 @@ static bool test_stream_decoder()
        expected_metadata_sequence_[num_expected_++] = &cuesheet_;
        expected_metadata_sequence_[num_expected_++] = &unknown_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
        /*
@@ -782,21 +1039,11 @@ static bool test_stream_decoder()
        num_expected_ = 0;
        expected_metadata_sequence_[num_expected_++] = &application2_;
 
-       if(!decoder->test_respond())
+       if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
                return false;
 
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       ::fclose(decoder->file_);
+       if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
+               ::fclose(dynamic_cast<StreamDecoder*>(decoder)->file_);
 
        printf("freeing decoder instance... ");
        delete decoder;
@@ -807,1401 +1054,26 @@ static bool test_stream_decoder()
        return true;
 }
 
-class SeekableStreamDecoder : public OggFLAC::Decoder::SeekableStream, public DecoderCommon {
-public:
-       SeekableStreamDecoder(): OggFLAC::Decoder::SeekableStream(), DecoderCommon() { }
-       ~SeekableStreamDecoder() { }
-
-       // from OggFLAC::Decoder::SeekableStream
-       ::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);
-       void error_callback(::FLAC__StreamDecoderErrorStatus status);
-
-       bool die(const char *msg = 0) const;
-
-       bool test_respond();
-};
-
-::OggFLAC__SeekableStreamDecoderReadStatus SeekableStreamDecoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
+bool test_decoders()
 {
-       switch(common_read_callback_(buffer, bytes)) {
-               case ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE:
-               case ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM:
-                       return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-               case ::FLAC__STREAM_DECODER_READ_STATUS_ABORT:
-                       return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-               default:
-                       FLAC__ASSERT(0);
-                       return ::OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-       }
-}
+       init_metadata_blocks_();
 
-::OggFLAC__SeekableStreamDecoderSeekStatus SeekableStreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset)
-{
-       if(error_occurred_)
-               return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
+       if(!generate_file_())
+               return false;
 
-       if(fseeko(file_, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
-               error_occurred_ = true;
-               return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-       }
-
-       return ::OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-::OggFLAC__SeekableStreamDecoderTellStatus SeekableStreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
-{
-       if(error_occurred_)
-               return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-
-       off_t offset = ftello(file_);
-       *absolute_byte_offset = (FLAC__uint64)offset;
-
-       if(offset < 0) {
-               error_occurred_ = true;
-               return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-       }
-
-       return ::OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
-}
-
-::OggFLAC__SeekableStreamDecoderLengthStatus SeekableStreamDecoder::length_callback(FLAC__uint64 *stream_length)
-{
-       if(error_occurred_)
-               return ::OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
-
-       *stream_length = (FLAC__uint64)oggflacfilesize_;
-       return ::OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
-}
-
-bool SeekableStreamDecoder::eof_callback()
-{
-       if(error_occurred_)
-               return true;
-
-       return (bool)feof(file_);
-}
-
-::FLAC__StreamDecoderWriteStatus SeekableStreamDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
-{
-       (void)buffer;
-
-       return common_write_callback_(frame);
-}
-
-void SeekableStreamDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
-{
-       common_metadata_callback_(metadata);
-}
-
-void SeekableStreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
-{
-       common_error_callback_(status);
-}
-
-bool SeekableStreamDecoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state), state.as_cstring());
-       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());
-               }
-       }
-
-       return false;
-}
-
-bool SeekableStreamDecoder::test_respond()
-{
-       if(!set_md5_checking(true)) {
-               printf("FAILED at set_md5_checking(), returned false\n");
-               return false;
-       }
-
-       printf("testing init()... ");
-       if(init() != ::OggFLAC__SEEKABLE_STREAM_DECODER_OK)
-               return die();
-       printf("OK\n");
-
-       current_metadata_number_ = 0;
-
-       if(fseeko(file_, 0, SEEK_SET) < 0) {
-               printf("FAILED rewinding input, errno = %d\n", errno);
-               return false;
-       }
-
-       printf("testing process_until_end_of_stream()... ");
-       if(!process_until_end_of_stream()) {
-               State state = get_state();
-               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::OggFLAC__SeekableStreamDecoderState)state), state.as_cstring());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       finish();
-       printf("OK\n");
-
-       return true;
-}
-
-static bool test_seekable_stream_decoder()
-{
-       SeekableStreamDecoder *decoder;
-
-       printf("\n+++ libOggFLAC++ unit test: OggFLAC::Decoder::SeekableStream\n\n");
-
-       //
-       // test new -> delete
-       //
-       printf("allocating decoder instance... ");
-       decoder = new SeekableStreamDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       //
-       // test new -> init -> delete
-       //
-       printf("allocating decoder instance... ");
-       decoder = new SeekableStreamDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(decoder->init() != ::OggFLAC__SEEKABLE_STREAM_DECODER_OK)
-               return decoder->die();
-       printf("OK\n");
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       //
-       // test normal usage
-       //
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-
-       printf("allocating decoder instance... ");
-       decoder = new SeekableStreamDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_md5_checking()... ");
-       if(!decoder->set_md5_checking(true)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_serial_number()... ");
-       if(!decoder->set_serial_number(file_utils__serial_number))
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(decoder->init() != ::OggFLAC__SEEKABLE_STREAM_DECODER_OK)
-               return decoder->die();
-       printf("OK\n");
-
-       printf("testing get_state()... ");
-       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_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();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state__), state__.as_cstring());
-
-       decoder->current_metadata_number_ = 0;
-       decoder->ignore_errors_ = false;
-       decoder->error_occurred_ = false;
-
-       printf("opening Ogg FLAC file... ");
-       decoder->file_ = ::fopen(oggflacfilename_, "rb");
-       if(0 == decoder->file_) {
-               printf("ERROR (%s)\n", strerror(errno));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_md5_checking()... ");
-       if(!decoder->get_md5_checking()) {
-               printf("FAILED, returned false, expected true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing process_until_end_of_metadata()... ");
-       if(!decoder->process_until_end_of_metadata())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_single()... ");
-       if(!decoder->process_single())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing flush()... ");
-       if(!decoder->flush())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       decoder->ignore_errors_ = true;
-       printf("testing process_single()... ");
-       if(!decoder->process_single())
-               return decoder->die("returned false");
-       printf("OK\n");
-       decoder->ignore_errors_ = false;
-
-       printf("testing seek_absolute()... ");
-       if(!decoder->seek_absolute(0))
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_until_end_of_stream()... ");
-       if(!decoder->process_until_end_of_stream())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing get_channels()... ");
-       {
-               unsigned channels = decoder->get_channels();
-               if(channels != streaminfo_.data.stream_info.channels) {
-                       printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_bits_per_sample()... ");
-       {
-               unsigned bits_per_sample = decoder->get_bits_per_sample();
-               if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
-                       printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_sample_rate()... ");
-       {
-               unsigned sample_rate = decoder->get_sample_rate();
-               if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
-                       printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_blocksize()... ");
-       {
-               unsigned blocksize = decoder->get_blocksize();
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
-       }
-
-       printf("testing get_channel_assignment()... ");
-       {
-               ::FLAC__ChannelAssignment ca = decoder->get_channel_assignment();
-               printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
-       }
-
-       printf("testing reset()... ");
-       if(!decoder->reset())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       decoder->current_metadata_number_ = 0;
-
-       printf("rewinding input... ");
-       if(fseeko(decoder->file_, 0, SEEK_SET) < 0) {
-               printf("FAILED, errno = %d\n", errno);
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing process_until_end_of_stream()... ");
-       if(!decoder->process_until_end_of_stream())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       decoder->finish();
-       printf("OK\n");
-
-       /*
-        * respond all
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore VORBIS_COMMENT
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(VORBIS_COMMENT)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(APPLICATION)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #2)... ");
-       if(!decoder->set_metadata_ignore_application(application2_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond VORBIS_COMMENT
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(VORBIS_COMMENT)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(APPLICATION)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #2)... ");
-       if(!decoder->set_metadata_respond_application(application2_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION, respond APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(APPLICATION)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(APPLICATION)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       ::fclose(decoder->file_);
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-class FileDecoder : public OggFLAC::Decoder::File, public DecoderCommon {
-public:
-       FileDecoder(): OggFLAC::Decoder::File(), DecoderCommon() { }
-       ~FileDecoder() { }
-
-       // from OggFLAC::Decoder::File
-       ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
-       void metadata_callback(const ::FLAC__StreamMetadata *metadata);
-       void error_callback(::FLAC__StreamDecoderErrorStatus status);
-
-       bool die(const char *msg = 0) const;
-
-       bool test_respond();
-};
-
-::FLAC__StreamDecoderWriteStatus FileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
-{
-       (void)buffer;
-       return common_write_callback_(frame);
-}
-
-void FileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
-{
-       common_metadata_callback_(metadata);
-}
-
-void FileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
-{
-       common_error_callback_(status);
-}
-
-bool FileDecoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__FileDecoderState)state), state.as_cstring());
-       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_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());
-                       }
-               }
-       }
-
-       return false;
-}
-
-bool FileDecoder::test_respond()
-{
-       if(!set_filename(oggflacfilename_)) {
-               printf("FAILED at set_filename(), returned false\n");
-               return false;
-       }
-
-       if(!set_md5_checking(true)) {
-               printf("FAILED at set_md5_checking(), returned false\n");
-               return false;
-       }
-
-       printf("testing init()... ");
-       if(init() != ::OggFLAC__FILE_DECODER_OK)
-               return die();
-       printf("OK\n");
-
-       current_metadata_number_ = 0;
-
-       printf("testing process_until_end_of_file()... ");
-       if(!process_until_end_of_file()) {
-               State state = get_state();
-               printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::OggFLAC__FileDecoderState)state), state.as_cstring());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       finish();
-       printf("OK\n");
-
-       return true;
-}
-
-static bool test_file_decoder()
-{
-       FileDecoder *decoder;
-
-       printf("\n+++ libOggFLAC++ unit test: OggFLAC::Decoder::File\n\n");
-
-       //
-       // test new -> delete
-       //
-       printf("allocating decoder instance... ");
-       decoder = new FileDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       //
-       // test new -> init -> delete
-       //
-       printf("allocating decoder instance... ");
-       decoder = new FileDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(decoder->init() != ::OggFLAC__FILE_DECODER_OK)
-               return decoder->die();
-       printf("OK\n");
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       //
-       // test normal usage
-       //
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-
-       printf("allocating decoder instance... ");
-       decoder = new FileDecoder();
-       if(0 == decoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!decoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_filename()... ");
-       if(!decoder->set_filename(oggflacfilename_)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_md5_checking()... ");
-       if(!decoder->set_md5_checking(true)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_serial_number()... ");
-       if(!decoder->set_serial_number(file_utils__serial_number))
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(decoder->init() != ::OggFLAC__FILE_DECODER_OK)
-               return decoder->die();
-       printf("OK\n");
-
-       printf("testing get_state()... ");
-       OggFLAC::Decoder::File::State state = decoder->get_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__FileDecoderState)state), state.as_cstring());
-
-       printf("testing get_seekable_stream_decoder_state()... ");
-       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_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();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state___), state___.as_cstring());
-
-       decoder->current_metadata_number_ = 0;
-       decoder->ignore_errors_ = false;
-       decoder->error_occurred_ = false;
-
-       printf("testing get_md5_checking()... ");
-       if(!decoder->get_md5_checking()) {
-               printf("FAILED, returned false, expected true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing process_until_end_of_metadata()... ");
-       if(!decoder->process_until_end_of_metadata())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_single()... ");
-       if(!decoder->process_single())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing seek_absolute()... ");
-       if(!decoder->seek_absolute(0))
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_until_end_of_file()... ");
-       if(!decoder->process_until_end_of_file())
-               return decoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing get_channels()... ");
-       {
-               unsigned channels = decoder->get_channels();
-               if(channels != streaminfo_.data.stream_info.channels) {
-                       printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_bits_per_sample()... ");
-       {
-               unsigned bits_per_sample = decoder->get_bits_per_sample();
-               if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
-                       printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_sample_rate()... ");
-       {
-               unsigned sample_rate = decoder->get_sample_rate();
-               if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
-                       printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing get_blocksize()... ");
-       {
-               unsigned blocksize = decoder->get_blocksize();
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
-       }
-
-       printf("testing get_channel_assignment()... ");
-       {
-               ::FLAC__ChannelAssignment ca = decoder->get_channel_assignment();
-               printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
-       }
-
-       printf("testing finish()... ");
-       decoder->finish();
-       printf("OK\n");
-
-       /*
-        * respond all
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore VORBIS_COMMENT
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(VORBIS_COMMENT)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(APPLICATION)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #2)... ");
-       if(!decoder->set_metadata_ignore_application(application2_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond VORBIS_COMMENT
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(VORBIS_COMMENT)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(APPLICATION)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #2)... ");
-       if(!decoder->set_metadata_respond_application(application2_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION, respond APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_respond_all()... ");
-       if(!decoder->set_metadata_respond_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore(APPLICATION)... ");
-       if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond_application(of app block #1)... ");
-       if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
-        */
-
-       printf("testing set_metadata_ignore_all()... ");
-       if(!decoder->set_metadata_ignore_all()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_respond(APPLICATION)... ");
-       if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_metadata_ignore_application(of app block #1)... ");
-       if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!decoder->test_respond())
-               return false;
-
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       printf("freeing decoder instance... ");
-       delete decoder;
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-bool test_decoders()
-{
-       init_metadata_blocks_();
-
-       if(!generate_file_())
+       if(!test_stream_decoder(LAYER_STREAM))
                return false;
 
-       if(!test_stream_decoder())
+       if(!test_stream_decoder(LAYER_SEEKABLE_STREAM))
                return false;
 
-       if(!test_seekable_stream_decoder())
+       if(!test_stream_decoder(LAYER_FILE))
                return false;
 
-       if(!test_file_decoder())
+       if(!test_stream_decoder(LAYER_FILENAME))
                return false;
 
-       (void) grabbag__file_remove_file(oggflacfilename_);
+       (void) grabbag__file_remove_file(flacfilename_);
 
        free_metadata_blocks_();
 
index b22d1a1..d2c7f69 100644 (file)
  */
 
 #include "encoders.h"
-extern "C" {
-#include "file_utils.h"
-#include "metadata_utils.h"
-}
 #include "FLAC/assert.h"
 #include "OggFLAC++/encoder.h"
+extern "C" {
+#include "test_libs_common/file_utils_oggflac.h"
+#include "test_libs_common/metadata_utils.h"
+}
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+typedef enum {
+       LAYER_STREAM = 0, /* FLAC__stream_encoder_init_stream() without seeking */
+       LAYER_SEEKABLE_STREAM, /* FLAC__stream_encoder_init_stream() with seeking */
+       LAYER_FILE, /* FLAC__stream_encoder_init_FILE() */
+       LAYER_FILENAME /* FLAC__stream_encoder_init_file() */
+} Layer;
+
+static const char * const LayerString[] = {
+       "Stream",
+       "Seekable Stream",
+       "FILE*",
+       "Filename"
+};
+
 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
 static ::FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &unknown_ };
 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
-static const char *oggflacfilename_ = "metadata.ogg";
+static const char *flacfilename_ = "metadata.ogg";
+
+static FLAC__bool die_(const char *msg)
+{
+       printf("ERROR: %s\n", msg);
+       return false;
+}
+
+static bool die_s_(const char *msg, const OggFLAC::Encoder::Stream *encoder)
+{
+       OggFLAC::Encoder::Stream::State state = encoder->get_state();
+
+       if(msg)
+               printf("FAILED, %s", msg);
+       else
+               printf("FAILED");
+
+       printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__StreamEncoderState)state), state.as_cstring());
+       if(state == ::OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) {
+               FLAC::Encoder::Stream::State state_ = encoder->get_FLAC_stream_encoder_state();
+               printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
+               if(state_ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
+                       FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
+                       printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
+               }
+       }
+
+       return false;
+}
 
 static void init_metadata_blocks_()
 {
@@ -44,16 +87,26 @@ static void free_metadata_blocks_()
 
 class StreamEncoder : public OggFLAC::Encoder::Stream {
 public:
-       StreamEncoder(): OggFLAC::Encoder::Stream() { }
+       Layer layer_;
+
+       StreamEncoder(Layer layer): OggFLAC::Encoder::Stream(), layer_(layer) { }
        ~StreamEncoder() { }
 
        // from OggFLAC::Encoder::Stream
+       ::OggFLAC__StreamEncoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
        ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame);
+       ::FLAC__StreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
+       ::FLAC__StreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
        void metadata_callback(const ::FLAC__StreamMetadata *metadata);
-
-       bool die(const char *msg = 0) const;
 };
 
+::OggFLAC__StreamEncoderReadStatus StreamEncoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
+{
+       (void)buffer, (void)bytes;
+
+       return ::OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE;
+}
+
 ::FLAC__StreamEncoderWriteStatus StreamEncoder::write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame)
 {
        (void)buffer, (void)bytes, (void)samples, (void)current_frame;
@@ -61,44 +114,61 @@ public:
        return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
 }
 
+::FLAC__StreamEncoderSeekStatus StreamEncoder::seek_callback(FLAC__uint64 absolute_byte_offset)
+{
+       (void)absolute_byte_offset;
+
+       return layer_==LAYER_STREAM? ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED : ::FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+}
+
+::FLAC__StreamEncoderTellStatus StreamEncoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
+{
+       *absolute_byte_offset = 0;
+
+       return layer_==LAYER_STREAM? ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED : ::FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+}
+
 void StreamEncoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
 {
        (void)metadata;
 }
 
-bool StreamEncoder::die(const char *msg) const
-{
-       State state = get_state();
+class FileEncoder : public OggFLAC::Encoder::File {
+public:
+       Layer layer_;
 
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
+       FileEncoder(Layer layer): OggFLAC::Encoder::File(), layer_(layer) { }
+       ~FileEncoder() { }
 
-       printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__StreamEncoderState)state), state.as_cstring());
-       if(state == ::OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) {
-               FLAC::Encoder::Stream::State state_ = get_FLAC_stream_encoder_state();
-               printf("      FLAC stream encoder state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
-               if(state_ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                       FLAC::Decoder::Stream::State dstate = get_verify_decoder_state();
-                       printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-               }
-       }
+       // from OggFLAC::Encoder::File
+       void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate);
+};
 
-       return false;
+void FileEncoder::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate)
+{
+       (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate;
+}
+
+static OggFLAC::Encoder::Stream *new_by_layer(Layer layer)
+{
+       if(layer < LAYER_FILE)
+               return new StreamEncoder(layer);
+       else
+               return new FileEncoder(layer);
 }
 
-static bool test_stream_encoder()
+static bool test_stream_encoder(Layer layer)
 {
-       StreamEncoder *encoder;
+       OggFLAC::Encoder::Stream *encoder;
+       FILE *file = 0;
        FLAC__int32 samples[1024];
        FLAC__int32 *samples_array[1] = { samples };
        unsigned i;
 
-       printf("\n+++ libOggFLAC++ unit test: OggFLAC::Encoder::Stream\n\n");
+       printf("\n+++ libOggFLAC++ unit test: OggFLAC::Encoder::%s (layer: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer]);
 
        printf("allocating encoder instance... ");
-       encoder = new StreamEncoder();
+       encoder = new_by_layer(layer);
        if(0 == encoder) {
                printf("FAILED, new returned NULL\n");
                return false;
@@ -114,102 +184,128 @@ static bool test_stream_encoder()
 
        printf("testing set_serial_number()... ");
        if(!encoder->set_serial_number(file_utils__serial_number))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_verify()... ");
        if(!encoder->set_verify(true))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_streamable_subset()... ");
        if(!encoder->set_streamable_subset(true))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_do_mid_side_stereo()... ");
        if(!encoder->set_do_mid_side_stereo(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_loose_mid_side_stereo()... ");
        if(!encoder->set_loose_mid_side_stereo(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_channels()... ");
        if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_bits_per_sample()... ");
        if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_sample_rate()... ");
        if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_blocksize()... ");
        if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_max_lpc_order()... ");
        if(!encoder->set_max_lpc_order(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_qlp_coeff_precision()... ");
        if(!encoder->set_qlp_coeff_precision(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_do_qlp_coeff_prec_search()... ");
        if(!encoder->set_do_qlp_coeff_prec_search(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_do_escape_coding()... ");
        if(!encoder->set_do_escape_coding(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_do_exhaustive_model_search()... ");
        if(!encoder->set_do_exhaustive_model_search(false))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_min_residual_partition_order()... ");
        if(!encoder->set_min_residual_partition_order(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_max_residual_partition_order()... ");
        if(!encoder->set_max_residual_partition_order(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_rice_parameter_search_dist()... ");
        if(!encoder->set_rice_parameter_search_dist(0))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_total_samples_estimate()... ");
        if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing set_metadata()... ");
        if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
-               return encoder->die("returned false");
-       printf("OK\n");
+               return die_s_("returned false", encoder);
+       printf("OK\n");
+
+       switch(layer) {
+               case LAYER_STREAM:
+               case LAYER_SEEKABLE_STREAM:
+                       printf("testing init()... ");
+                       if(encoder->init() != ::FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_FILE:
+                       printf("opening file for Ogg FLAC output... ");
+                       file = ::fopen(flacfilename_, "w+b");
+                       if(0 == file) {
+                               printf("ERROR (%s)\n", strerror(errno));
+                               return false;
+                       }
+                       printf("OK\n");
 
-       printf("testing init()... ");
-       if(encoder->init() != ::OggFLAC__STREAM_ENCODER_OK)
-               return encoder->die();
+                       printf("testing init()... ");
+                       if(dynamic_cast<OggFLAC::Encoder::File*>(encoder)->init(file) != ::FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing init()... ");
+                       if(dynamic_cast<OggFLAC::Encoder::File*>(encoder)->init(flacfilename_) != ::FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               default:
+                       die_("internal error 001");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing get_state()... ");
@@ -360,12 +456,12 @@ static bool test_stream_encoder()
 
        printf("testing process()... ");
        if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing process_interleaved()... ");
        if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
+               return die_s_("returned false", encoder);
        printf("OK\n");
 
        printf("testing finish()... ");
@@ -381,717 +477,20 @@ static bool test_stream_encoder()
        return true;
 }
 
-class SeekableStreamEncoder : public OggFLAC::Encoder::SeekableStream {
-public:
-       SeekableStreamEncoder(): OggFLAC::Encoder::SeekableStream() { }
-       ~SeekableStreamEncoder() { }
-
-       // from OggFLAC::Encoder::SeekableStream
-       ::OggFLAC__SeekableStreamEncoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes);
-       ::FLAC__SeekableStreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
-       ::FLAC__SeekableStreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
-       ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame);
-
-       bool die(const char *msg = 0) const;
-};
-
-::OggFLAC__SeekableStreamEncoderReadStatus SeekableStreamEncoder::read_callback(FLAC__byte buffer[], unsigned *bytes)
-{
-       (void)buffer, (void)bytes;
-       ::memset(buffer, 0, *bytes); /* init buffer to avoid valgrind errors */
-       return ::OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE;
-}
-
-::FLAC__SeekableStreamEncoderSeekStatus SeekableStreamEncoder::seek_callback(FLAC__uint64 absolute_byte_offset)
-{
-       (void)absolute_byte_offset;
-
-       return ::FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
-}
-
-::FLAC__SeekableStreamEncoderTellStatus SeekableStreamEncoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
-{
-       (void)absolute_byte_offset;
-
-       return ::FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK;
-}
-
-::FLAC__StreamEncoderWriteStatus SeekableStreamEncoder::write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame)
-{
-       (void)buffer, (void)bytes, (void)samples, (void)current_frame;
-
-       return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-}
-
-bool SeekableStreamEncoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__SeekableStreamEncoderState)state), state.as_cstring());
-       if(state == ::OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) {
-               FLAC::Encoder::Stream::State state_ = get_FLAC_stream_encoder_state();
-               printf("      FLAC stream encoder state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
-               if(state_ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                       FLAC::Decoder::Stream::State dstate = get_verify_decoder_state();
-                       printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-               }
-       }
-
-       return false;
-}
-
-static bool test_seekable_stream_encoder()
+bool test_encoders()
 {
-       SeekableStreamEncoder *encoder;
-       FLAC__int32 samples[1024];
-       FLAC__int32 *samples_array[1] = { samples };
-       unsigned i;
-
-       printf("\n+++ libOggFLAC++ unit test: OggFLAC::Encoder::SeekableStream\n\n");
-
-       printf("allocating encoder instance... ");
-       encoder = new SeekableStreamEncoder();
-       if(0 == encoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!encoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_serial_number()... ");
-       if(!encoder->set_serial_number(file_utils__serial_number))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_verify()... ");
-       if(!encoder->set_verify(true))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_streamable_subset()... ");
-       if(!encoder->set_streamable_subset(true))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_mid_side_stereo()... ");
-       if(!encoder->set_do_mid_side_stereo(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_loose_mid_side_stereo()... ");
-       if(!encoder->set_loose_mid_side_stereo(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_channels()... ");
-       if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_bits_per_sample()... ");
-       if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_sample_rate()... ");
-       if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_blocksize()... ");
-       if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_max_lpc_order()... ");
-       if(!encoder->set_max_lpc_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_qlp_coeff_precision()... ");
-       if(!encoder->set_qlp_coeff_precision(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_qlp_coeff_prec_search()... ");
-       if(!encoder->set_do_qlp_coeff_prec_search(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_escape_coding()... ");
-       if(!encoder->set_do_escape_coding(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_exhaustive_model_search()... ");
-       if(!encoder->set_do_exhaustive_model_search(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_min_residual_partition_order()... ");
-       if(!encoder->set_min_residual_partition_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_max_residual_partition_order()... ");
-       if(!encoder->set_max_residual_partition_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_rice_parameter_search_dist()... ");
-       if(!encoder->set_rice_parameter_search_dist(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_total_samples_estimate()... ");
-       if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_metadata()... ");
-       if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(encoder->init() != ::OggFLAC__SEEKABLE_STREAM_ENCODER_OK)
-               return encoder->die();
-       printf("OK\n");
-
-       printf("testing get_state()... ");
-       OggFLAC::Encoder::SeekableStream::State state = encoder->get_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__SeekableStreamEncoderState)state), state.as_cstring());
-
-       printf("testing get_FLAC_stream_encoder_state()... ");
-       FLAC::Encoder::Stream::State state_ = encoder->get_FLAC_stream_encoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
-
-       printf("testing get_verify_decoder_state()... ");
-       FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-
-       {
-               FLAC__uint64 absolute_sample;
-               unsigned frame_number;
-               unsigned channel;
-               unsigned sample;
-               FLAC__int32 expected;
-               FLAC__int32 got;
-
-               printf("testing get_verify_decoder_error_stats()... ");
-               encoder->get_verify_decoder_error_stats(&absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               printf("OK\n");
-       }
-
-       printf("testing get_verify()... ");
-       if(encoder->get_verify() != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_streamable_subset()... ");
-       if(encoder->get_streamable_subset() != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_mid_side_stereo()... ");
-       if(encoder->get_do_mid_side_stereo() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
+       init_metadata_blocks_();
 
-       printf("testing get_loose_mid_side_stereo()... ");
-       if(encoder->get_loose_mid_side_stereo() != false) {
-               printf("FAILED, expected false, got true\n");
+       if(!test_stream_encoder(LAYER_STREAM))
                return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_channels()... ");
-       if(encoder->get_channels() != streaminfo_.data.stream_info.channels) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, encoder->get_channels());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_bits_per_sample()... ");
-       if(encoder->get_bits_per_sample() != streaminfo_.data.stream_info.bits_per_sample) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, encoder->get_bits_per_sample());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_sample_rate()... ");
-       if(encoder->get_sample_rate() != streaminfo_.data.stream_info.sample_rate) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, encoder->get_sample_rate());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_blocksize()... ");
-       if(encoder->get_blocksize() != streaminfo_.data.stream_info.min_blocksize) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, encoder->get_blocksize());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_max_lpc_order()... ");
-       if(encoder->get_max_lpc_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_lpc_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_qlp_coeff_precision()... ");
-       (void)encoder->get_qlp_coeff_precision();
-       /* we asked the encoder to auto select this so we accept anything */
-       printf("OK\n");
-
-       printf("testing get_do_qlp_coeff_prec_search()... ");
-       if(encoder->get_do_qlp_coeff_prec_search() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_escape_coding()... ");
-       if(encoder->get_do_escape_coding() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_exhaustive_model_search()... ");
-       if(encoder->get_do_exhaustive_model_search() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_min_residual_partition_order()... ");
-       if(encoder->get_min_residual_partition_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_min_residual_partition_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_max_residual_partition_order()... ");
-       if(encoder->get_max_residual_partition_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_residual_partition_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_rice_parameter_search_dist()... ");
-       if(encoder->get_rice_parameter_search_dist() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_rice_parameter_search_dist());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_total_samples_estimate()... ");
-       if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
-               printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
-               return false;
-       }
-       printf("OK\n");
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       printf("testing process()... ");
-       if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_interleaved()... ");
-       if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       encoder->finish();
-       printf("OK\n");
-
-       printf("freeing encoder instance... ");
-       delete encoder;
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-class FileEncoder : public OggFLAC::Encoder::File {
-public:
-       FileEncoder(): OggFLAC::Encoder::File() { }
-       ~FileEncoder() { }
-
-       // from OggFLAC::Encoder::File
-       void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate);
-
-       bool die(const char *msg = 0) const;
-};
-
-void FileEncoder::progress_callback(FLAC__uint64, FLAC__uint64, unsigned, unsigned)
-{
-}
-
-bool FileEncoder::die(const char *msg) const
-{
-       State state = get_state();
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__FileEncoderState)state), state.as_cstring());
-       if(state == ::OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR) {
-               OggFLAC::Encoder::SeekableStream::State state_ = get_seekable_stream_encoder_state();
-               printf("      seekable stream encoder state = %u (%s)\n", (unsigned)((::OggFLAC__SeekableStreamEncoderState)state_), state_.as_cstring());
-               if(state_ == ::OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) {
-                       FLAC::Encoder::Stream::State state__ = get_FLAC_stream_encoder_state();
-                       printf("      FLAC stream encoder state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state__), state__.as_cstring());
-                       if(state__ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                               FLAC::Decoder::Stream::State dstate = get_verify_decoder_state();
-                               printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-                       }
-               }
-       }
-
-       return false;
-}
-
-static bool test_file_encoder()
-{
-       FileEncoder *encoder;
-       FLAC__int32 samples[1024];
-       FLAC__int32 *samples_array[1] = { samples };
-       unsigned i;
-
-       printf("\n+++ libOggFLAC++ unit test: OggFLAC::Encoder::File\n\n");
-
-       printf("allocating encoder instance... ");
-       encoder = new FileEncoder();
-       if(0 == encoder) {
-               printf("FAILED, new returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing is_valid()... ");
-       if(!encoder->is_valid()) {
-               printf("FAILED, returned false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing set_serial_number()... ");
-       if(!encoder->set_serial_number(file_utils__serial_number))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_verify()... ");
-       if(!encoder->set_verify(true))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_streamable_subset()... ");
-       if(!encoder->set_streamable_subset(true))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_mid_side_stereo()... ");
-       if(!encoder->set_do_mid_side_stereo(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_loose_mid_side_stereo()... ");
-       if(!encoder->set_loose_mid_side_stereo(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_channels()... ");
-       if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_bits_per_sample()... ");
-       if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_sample_rate()... ");
-       if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_blocksize()... ");
-       if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_max_lpc_order()... ");
-       if(!encoder->set_max_lpc_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_qlp_coeff_precision()... ");
-       if(!encoder->set_qlp_coeff_precision(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_qlp_coeff_prec_search()... ");
-       if(!encoder->set_do_qlp_coeff_prec_search(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_escape_coding()... ");
-       if(!encoder->set_do_escape_coding(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_do_exhaustive_model_search()... ");
-       if(!encoder->set_do_exhaustive_model_search(false))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_min_residual_partition_order()... ");
-       if(!encoder->set_min_residual_partition_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_max_residual_partition_order()... ");
-       if(!encoder->set_max_residual_partition_order(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_rice_parameter_search_dist()... ");
-       if(!encoder->set_rice_parameter_search_dist(0))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_total_samples_estimate()... ");
-       if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_metadata()... ");
-       if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing set_filename()... ");
-       if(!encoder->set_filename(oggflacfilename_))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing init()... ");
-       if(encoder->init() != ::OggFLAC__FILE_ENCODER_OK)
-               return encoder->die();
-       printf("OK\n");
-
-       printf("testing get_state()... ");
-       OggFLAC::Encoder::File::State state = encoder->get_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__FileEncoderState)state), state.as_cstring());
-
-       printf("testing get_seekable_stream_encoder_state()... ");
-       OggFLAC::Encoder::SeekableStream::State state_ = encoder->get_seekable_stream_encoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__SeekableStreamEncoderState)state_), state_.as_cstring());
-
-       printf("testing get_FLAC_stream_encoder_state()... ");
-       FLAC::Encoder::Stream::State state__ = encoder->get_FLAC_stream_encoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state__), state__.as_cstring());
-
-       printf("testing get_verify_decoder_state()... ");
-       FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
-       printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
-
-       {
-               FLAC__uint64 absolute_sample;
-               unsigned frame_number;
-               unsigned channel;
-               unsigned sample;
-               FLAC__int32 expected;
-               FLAC__int32 got;
-
-               printf("testing get_verify_decoder_error_stats()... ");
-               encoder->get_verify_decoder_error_stats(&absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               printf("OK\n");
-       }
-
-       printf("testing get_verify()... ");
-       if(encoder->get_verify() != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_streamable_subset()... ");
-       if(encoder->get_streamable_subset() != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_mid_side_stereo()... ");
-       if(encoder->get_do_mid_side_stereo() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_loose_mid_side_stereo()... ");
-       if(encoder->get_loose_mid_side_stereo() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_channels()... ");
-       if(encoder->get_channels() != streaminfo_.data.stream_info.channels) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, encoder->get_channels());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_bits_per_sample()... ");
-       if(encoder->get_bits_per_sample() != streaminfo_.data.stream_info.bits_per_sample) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, encoder->get_bits_per_sample());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_sample_rate()... ");
-       if(encoder->get_sample_rate() != streaminfo_.data.stream_info.sample_rate) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, encoder->get_sample_rate());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_blocksize()... ");
-       if(encoder->get_blocksize() != streaminfo_.data.stream_info.min_blocksize) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, encoder->get_blocksize());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_max_lpc_order()... ");
-       if(encoder->get_max_lpc_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_lpc_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_qlp_coeff_precision()... ");
-       (void)encoder->get_qlp_coeff_precision();
-       /* we asked the encoder to auto select this so we accept anything */
-       printf("OK\n");
-
-       printf("testing get_do_qlp_coeff_prec_search()... ");
-       if(encoder->get_do_qlp_coeff_prec_search() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_escape_coding()... ");
-       if(encoder->get_do_escape_coding() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_do_exhaustive_model_search()... ");
-       if(encoder->get_do_exhaustive_model_search() != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_min_residual_partition_order()... ");
-       if(encoder->get_min_residual_partition_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_min_residual_partition_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_max_residual_partition_order()... ");
-       if(encoder->get_max_residual_partition_order() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_residual_partition_order());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_rice_parameter_search_dist()... ");
-       if(encoder->get_rice_parameter_search_dist() != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, encoder->get_rice_parameter_search_dist());
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing get_total_samples_estimate()... ");
-       if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
-               printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
-               return false;
-       }
-       printf("OK\n");
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       printf("testing process()... ");
-       if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing process_interleaved()... ");
-       if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return encoder->die("returned false");
-       printf("OK\n");
-
-       printf("testing finish()... ");
-       encoder->finish();
-       printf("OK\n");
-
-       printf("freeing encoder instance... ");
-       delete encoder;
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-bool test_encoders()
-{
-       init_metadata_blocks_();
 
-       if(!test_stream_encoder())
+       if(!test_stream_encoder(LAYER_SEEKABLE_STREAM))
                return false;
 
-       if(!test_seekable_stream_encoder())
+       if(!test_stream_encoder(LAYER_FILE))
                return false;
 
-       if(!test_file_encoder())
+       if(!test_stream_encoder(LAYER_FILENAME))
                return false;
 
        free_metadata_blocks_();
diff --git a/src/test_libOggFLAC++/file_utils.h b/src/test_libOggFLAC++/file_utils.h
deleted file mode 100644 (file)
index d59127f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* test_libOggFLAC - Unit tester for libOggFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef OggFLAC__TEST_LIBOGGFLAC_FILE_UTILS_H
-#define OggFLAC__TEST_LIBOGGFLAC_FILE_UTILS_H
-
-/* needed because of off_t */
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "FLAC/format.h"
-#include <sys/types.h> /* for off_t */
-
-extern const long file_utils__serial_number;
-
-FLAC__bool file_utils__generate_oggflacfile(const char *output_filename, off_t *output_filesize, unsigned length, const FLAC__StreamMetadata *streaminfo, FLAC__StreamMetadata **metadata, unsigned num_metadata);
-
-#endif
diff --git a/src/test_libOggFLAC++/metadata_utils.h b/src/test_libOggFLAC++/metadata_utils.h
deleted file mode 100644 (file)
index 3d7af19..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* test_libFLAC - Unit tester for libFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef FLAC__TEST_LIBFLAC_METADATA_H
-#define FLAC__TEST_LIBFLAC_METADATA_H
-
-/*
- * These are not tests, just utility functions used by the metadata tests
- */
-
-#include "FLAC/format.h"
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for memcmp() */
-
-FLAC__bool mutils__compare_block_data_streaminfo(const FLAC__StreamMetadata_StreamInfo *block, const FLAC__StreamMetadata_StreamInfo *blockcopy);
-
-FLAC__bool mutils__compare_block_data_padding(const FLAC__StreamMetadata_Padding *block, const FLAC__StreamMetadata_Padding *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block_data_application(const FLAC__StreamMetadata_Application *block, const FLAC__StreamMetadata_Application *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block_data_seektable(const FLAC__StreamMetadata_SeekTable *block, const FLAC__StreamMetadata_SeekTable *blockcopy);
-
-FLAC__bool mutils__compare_block_data_vorbiscomment(const FLAC__StreamMetadata_VorbisComment *block, const FLAC__StreamMetadata_VorbisComment *blockcopy);
-
-FLAC__bool mutils__compare_block_data_cuesheet(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy);
-
-FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length);
-
-FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy);
-
-void mutils__init_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-);
-
-void mutils__free_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-);
-
-#endif
index a1b6c06..63c458a 100644 (file)
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
-# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\libOggFLAC++_static.lib ..\..\obj\release\lib\libOggFLAC_static.lib ..\..\obj\release\lib\libFLAC++_static.lib ..\..\obj\release\lib\libFLAC_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\test_libs_common_static.lib ..\..\obj\release\lib\libOggFLAC++_static.lib ..\..\obj\release\lib\libOggFLAC_static.lib ..\..\obj\release\lib\libFLAC++_static.lib ..\..\obj\release\lib\libFLAC_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /machine:I386\r
 \r
 !ELSEIF  "$(CFG)" == "test_libOggFLAC++ - Win32 Debug"\r
 \r
@@ -76,7 +76,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\libOggFLAC++_static.lib ..\..\obj\debug\lib\libOggFLAC_static.lib ..\..\obj\debug\lib\libFLAC++_static.lib ..\..\obj\debug\lib\libFLAC_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\test_libs_common_static.lib ..\..\obj\debug\lib\libOggFLAC++_static.lib ..\..\obj\debug\lib\libOggFLAC_static.lib ..\..\obj\debug\lib\libFLAC++_static.lib ..\..\obj\debug\lib\libFLAC_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
 \r
 !ENDIF \r
 \r
@@ -97,16 +97,8 @@ SOURCE=.\encoders.cpp
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\file_utils.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\main.cpp\r
 # End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\metadata_utils.c\r
-# End Source File\r
 # End Group\r
 # Begin Group "Header Files"\r
 \r
@@ -119,14 +111,6 @@ SOURCE=.\decoders.h
 \r
 SOURCE=.\encoders.h\r
 # End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\file_utils.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\metadata_utils.h\r
-# End Source File\r
 # End Group\r
 # Begin Source File\r
 \r
index bd5efde..52bd131 100644 (file)
@@ -27,6 +27,7 @@ noinst_PROGRAMS = test_libOggFLAC
 test_libOggFLAC_LDADD = \
        $(top_builddir)/src/share/grabbag/libgrabbag.la \
        $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+       $(top_builddir)/src/test_libs_common/libtest_libs_common.la \
        $(top_builddir)/src/libOggFLAC/libOggFLAC.la \
        $(top_builddir)/src/libFLAC/libFLAC.la \
        @OGG_LIBS@ \
@@ -34,10 +35,6 @@ test_libOggFLAC_LDADD = \
 test_libOggFLAC_SOURCES = \
        decoders.c \
        encoders.c \
-       file_utils.c \
        main.c \
-       metadata_utils.c \
        decoders.h \
-       encoders.h \
-       file_utils.h \
-       metadata_utils.h
+       encoders.h
index 2776719..edc462f 100644 (file)
@@ -27,17 +27,15 @@ PROGRAM_NAME = test_libOggFLAC
 INCLUDES = -I$(topdir)/include
 
 ifeq ($(DARWIN_BUILD),yes)
-EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libreplaygain_analysis.a $(libdir)/libOggFLAC.a $(libdir)/libFLAC.a $(OGG_LIB_DIR)/libogg.a -lm
+EXPLICIT_LIBS = $(libdir)/libgrabbag.a $(libdir)/libreplaygain_analysis.a $(libdir)/libtest_libs_common.a $(libdir)/libOggFLAC.a $(libdir)/libFLAC.a $(OGG_LIB_DIR)/libogg.a -lm
 else
-LIBS = -lgrabbag -lreplaygain_analysis -lOggFLAC -lFLAC -L$(OGG_LIB_DIR) -logg -lm
+LIBS = -lgrabbag -lreplaygain_analysis -ltest_libs_common -lOggFLAC -lFLAC -L$(OGG_LIB_DIR) -logg -lm
 endif
 
 SRCS_C = \
        decoders.c \
        encoders.c \
-       file_utils.c \
-       main.c \
-       metadata_utils.c
+       main.c
 
 include $(topdir)/build/exe.mk
 
diff --git a/src/test_libOggFLAC/README b/src/test_libOggFLAC/README
deleted file mode 100644 (file)
index aef8a19..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-NOTE: the following files are copied from the ../test_libFLAC directory:
-
-       file_utils.c
-       file_utils.h
-       metadata_utils.c
-       metadata_utils.h
-
-It's too much of a pain to make a convenience library for these and CVS
-can't do soft links, so we put up with having two copies of these sources.
-
-file_utils.c and file_utils.h have trivial changes for use in this package.
index 2f356be..f02abbc 100644 (file)
 #define ftello ftell
 #endif
 #include "decoders.h"
-#include "file_utils.h"
-#include "metadata_utils.h"
 #include "FLAC/assert.h"
-#include "OggFLAC/file_decoder.h"
-#include "OggFLAC/seekable_stream_decoder.h"
 #include "OggFLAC/stream_decoder.h"
 #include "share/grabbag.h"
+#include "test_libs_common/file_utils_oggflac.h"
+#include "test_libs_common/metadata_utils.h"
+
+//@@@@@@ this is almost exactly like test_libFLAC/decoders.c, maybe should consolidate some stuff liek client data and callbacks
+typedef enum {
+       LAYER_STREAM = 0, /* FLAC__stream_decoder_init_stream() without seeking */
+       LAYER_SEEKABLE_STREAM, /* FLAC__stream_decoder_init_stream() with seeking */
+       LAYER_FILE, /* FLAC__stream_decoder_init_FILE() */
+       LAYER_FILENAME /* FLAC__stream_decoder_init_file() */
+} Layer;
+
+static const char * const LayerString[] = {
+       "Stream",
+       "Seekable Stream",
+       "FILE*",
+       "Filename"
+};
 
 typedef struct {
+       Layer layer;
        FILE *file;
        unsigned current_metadata_number;
        FLAC__bool ignore_errors;
        FLAC__bool error_occurred;
-} stream_decoder_client_data_struct;
-
-typedef stream_decoder_client_data_struct seekable_stream_decoder_client_data_struct;
-typedef stream_decoder_client_data_struct file_decoder_client_data_struct;
+} StreamDecoderClientData;
 
 static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
 static FLAC__StreamMetadata *expected_metadata_sequence_[8];
 static unsigned num_expected_;
-static const char *oggflacfilename_ = "metadata.ogg";
-static off_t oggflacfilesize_;
+static const char *flacfilename_ = "metadata.ogg";
+static off_t flacfilesize_;
 
 static FLAC__bool die_(const char *msg)
 {
@@ -78,54 +89,6 @@ static FLAC__bool die_s_(const char *msg, const OggFLAC__StreamDecoder *decoder)
        return false;
 }
 
-static FLAC__bool die_ss_(const char *msg, const OggFLAC__SeekableStreamDecoder *decoder)
-{
-       OggFLAC__SeekableStreamDecoderState state = OggFLAC__seekable_stream_decoder_get_state(decoder);
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)state, OggFLAC__SeekableStreamDecoderStateString[state]);
-       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__]);
-               }
-       }
-
-       return false;
-}
-
-static FLAC__bool die_f_(const char *msg, const OggFLAC__FileDecoder *decoder)
-{
-       OggFLAC__FileDecoderState state = OggFLAC__file_decoder_get_state(decoder);
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)state, OggFLAC__SeekableStreamDecoderStateString[state]);
-       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_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___]);
-                       }
-               }
-       }
-
-       return false;
-}
-
 static void init_metadata_blocks_()
 {
        mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
@@ -150,15 +113,16 @@ static FLAC__bool generate_file_()
        expected_metadata_sequence_[num_expected_++] = &unknown_;
        /* WATCHOUT: the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
 
-       if(!file_utils__generate_oggflacfile(oggflacfilename_, &oggflacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
+       if(!file_utils__generate_oggflacfile(flacfilename_, &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
                return die_("creating the encoded file");
 
        return true;
 }
 
-static FLAC__StreamDecoderReadStatus stream_decoder_read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+static FLAC__StreamDecoderReadStatus stream_decoder_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
 {
-       stream_decoder_client_data_struct *dcd = (stream_decoder_client_data_struct*)client_data;
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+       const unsigned requested_bytes = *bytes;
 
        (void)decoder;
 
@@ -174,8 +138,8 @@ static FLAC__StreamDecoderReadStatus stream_decoder_read_callback_(const OggFLAC
                *bytes = 0;
                return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
        }
-       else if(*bytes > 0) {
-               *bytes = fread(buffer, 1, *bytes, dcd->file);
+       else if(requested_bytes > 0) {
+               *bytes = fread(buffer, 1, requested_bytes, dcd->file);
                if(*bytes == 0) {
                        if(feof(dcd->file))
                                return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
@@ -190,9 +154,92 @@ static FLAC__StreamDecoderReadStatus stream_decoder_read_callback_(const OggFLAC
                return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
 }
 
-static FLAC__StreamDecoderWriteStatus stream_decoder_write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+static FLAC__StreamDecoderSeekStatus stream_decoder_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+
+       (void)decoder;
+
+       if(0 == dcd) {
+               printf("ERROR: client_data in seek callback is NULL\n");
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+       }
+
+       if(dcd->error_occurred)
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+
+       if(fseeko(dcd->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
+               dcd->error_occurred = true;
+               return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+       }
+
+       return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+static FLAC__StreamDecoderTellStatus stream_decoder_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+       off_t offset;
+
+       (void)decoder;
+
+       if(0 == dcd) {
+               printf("ERROR: client_data in tell callback is NULL\n");
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+       }
+
+       if(dcd->error_occurred)
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+
+       offset = ftello(dcd->file);
+       *absolute_byte_offset = (FLAC__uint64)offset;
+
+       if(offset < 0) {
+               dcd->error_occurred = true;
+               return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+       }
+
+       return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+}
+
+static FLAC__StreamDecoderLengthStatus stream_decoder_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
 {
-       stream_decoder_client_data_struct *dcd = (stream_decoder_client_data_struct*)client_data;
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+
+       (void)decoder;
+
+       if(0 == dcd) {
+               printf("ERROR: client_data in length callback is NULL\n");
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+       }
+
+       if(dcd->error_occurred)
+               return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+
+       *stream_length = (FLAC__uint64)flacfilesize_;
+       return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+}
+
+static FLAC__bool stream_decoder_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data)
+{
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
+
+       (void)decoder;
+
+       if(0 == dcd) {
+               printf("ERROR: client_data in eof callback is NULL\n");
+               return true;
+       }
+
+       if(dcd->error_occurred)
+               return true;
+
+       return feof(dcd->file);
+}
+
+static FLAC__StreamDecoderWriteStatus stream_decoder_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+{
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
 
        (void)decoder, (void)buffer;
 
@@ -215,9 +262,9 @@ static FLAC__StreamDecoderWriteStatus stream_decoder_write_callback_(const OggFL
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
 
-static void stream_decoder_metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+static void stream_decoder_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
-       stream_decoder_client_data_struct *dcd = (stream_decoder_client_data_struct*)client_data;
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
 
        (void)decoder;
 
@@ -245,9 +292,9 @@ static void stream_decoder_metadata_callback_(const OggFLAC__StreamDecoder *deco
        dcd->current_metadata_number++;
 }
 
-static void stream_decoder_error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+static void stream_decoder_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
-       stream_decoder_client_data_struct *dcd = (stream_decoder_client_data_struct*)client_data;
+       StreamDecoderClientData *dcd = (StreamDecoderClientData*)client_data;
 
        (void)decoder;
 
@@ -262,31 +309,49 @@ static void stream_decoder_error_callback_(const OggFLAC__StreamDecoder *decoder
        }
 }
 
-static FLAC__bool stream_decoder_test_respond_(OggFLAC__StreamDecoder *decoder, stream_decoder_client_data_struct *dcd)
+static FLAC__bool stream_decoder_test_respond_(OggFLAC__StreamDecoder *decoder, StreamDecoderClientData *dcd)
 {
-       if(!OggFLAC__stream_decoder_set_read_callback(decoder, stream_decoder_read_callback_))
-               return die_s_("at OggFLAC__stream_decoder_set_read_callback(), returned false", decoder);
-
-       if(!OggFLAC__stream_decoder_set_write_callback(decoder, stream_decoder_write_callback_))
-               return die_s_("at OggFLAC__stream_decoder_set_write_callback(), returned false", decoder);
+       FLAC__StreamDecoderInitStatus init_status;
 
-       if(!OggFLAC__stream_decoder_set_metadata_callback(decoder, stream_decoder_metadata_callback_))
-               return die_s_("at OggFLAC__stream_decoder_set_metadata_callback(), returned false", decoder);
+       if(!OggFLAC__stream_decoder_set_md5_checking(decoder, true))
+               return die_s_("at OggFLAC__stream_decoder_set_md5_checking(), returned false", decoder);
 
-       if(!OggFLAC__stream_decoder_set_error_callback(decoder, stream_decoder_error_callback_))
-               return die_s_("at OggFLAC__stream_decoder_set_error_callback(), returned false", decoder);
-
-       if(!OggFLAC__stream_decoder_set_client_data(decoder, dcd))
-               return die_s_("at OggFLAC__stream_decoder_set_client_data(), returned false", decoder);
-
-       printf("testing OggFLAC__stream_decoder_init()... ");
-       if(OggFLAC__stream_decoder_init(decoder) != OggFLAC__STREAM_DECODER_OK)
+       /* for OggFLAC__stream_encoder_init_FILE(), the OggFLAC__stream_encoder_finish() closes the file so we have to keep re-opening: */
+       if(dcd->layer == LAYER_FILE) {
+               printf("opening Ogg FLAC file... ");
+               dcd->file = fopen(flacfilename_, "rb");
+               if(0 == dcd->file) {
+                       printf("ERROR (%s)\n", strerror(errno));
+                       return false;
+               }
+               printf("OK\n");
+       }
+
+       printf("testing OggFLAC__stream_decoder_init_stream()... ");
+       switch(dcd->layer) {
+               case LAYER_STREAM:
+                       init_status = OggFLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
+                       break;
+               case LAYER_SEEKABLE_STREAM:
+                       init_status = OggFLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, stream_decoder_seek_callback_, stream_decoder_tell_callback_, stream_decoder_length_callback_, stream_decoder_eof_callback_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
+                       break;
+               case LAYER_FILE:
+                       init_status = OggFLAC__stream_decoder_init_FILE(decoder, dcd->file, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
+                       break;
+               case LAYER_FILENAME:
+                       init_status = OggFLAC__stream_decoder_init_file(decoder, flacfilename_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, dcd);
+                       break;
+               default:
+                       die_("internal error 000");
+                       return false;
+       }
+       if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
                return die_s_(0, decoder);
        printf("OK\n");
 
        dcd->current_metadata_number = 0;
 
-       if(fseeko(dcd->file, 0, SEEK_SET) < 0) {
+       if(dcd->layer < LAYER_FILE && fseeko(dcd->file, 0, SEEK_SET) < 0) {
                printf("FAILED rewinding input, errno = %d\n", errno);
                return false;
        }
@@ -303,14 +368,17 @@ static FLAC__bool stream_decoder_test_respond_(OggFLAC__StreamDecoder *decoder,
        return true;
 }
 
-static FLAC__bool test_stream_decoder()
+static FLAC__bool test_stream_decoder(Layer layer)
 {
        OggFLAC__StreamDecoder *decoder;
        OggFLAC__StreamDecoderState state;
        FLAC__StreamDecoderState fstate;
-       stream_decoder_client_data_struct decoder_client_data;
+       StreamDecoderClientData decoder_client_data;
+       FLAC__bool expect;
+
+       decoder_client_data.layer = layer;
 
-       printf("\n+++ libOggFLAC unit test: OggFLAC__StreamDecoder\n\n");
+       printf("\n+++ libOggFLAC unit test: OggFLAC__StreamDecoder (layer: %s)\n\n", LayerString[layer]);
 
        printf("testing OggFLAC__stream_decoder_new()... ");
        decoder = OggFLAC__stream_decoder_new();
@@ -332,9 +400,27 @@ static FLAC__bool test_stream_decoder()
        }
        printf("OK\n");
 
-       printf("testing OggFLAC__stream_decoder_init()... ");
-       if(OggFLAC__stream_decoder_init(decoder) == OggFLAC__STREAM_DECODER_OK)
-               return die_s_(0, decoder);
+       switch(layer) {
+               case LAYER_STREAM:
+               case LAYER_SEEKABLE_STREAM:
+                       printf("testing OggFLAC__stream_decoder_init_stream()... ");
+                       if(OggFLAC__stream_decoder_init_stream(decoder, 0, 0, 0, 0, 0, 0, 0, 0, 0) != FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILE:
+                       printf("testing OggFLAC__stream_decoder_init_FILE()... ");
+                       if(OggFLAC__stream_decoder_init_FILE(decoder, stdin, 0, 0, 0, 0) != FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing OggFLAC__stream_decoder_init_file()... ");
+                       if(OggFLAC__stream_decoder_init_file(decoder, flacfilename_, 0, 0, 0, 0) != FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS)
+                               return die_s_(0, decoder);
+                       break;
+               default:
+                       die_("internal error 003");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing OggFLAC__stream_decoder_delete()... ");
@@ -357,34 +443,46 @@ static FLAC__bool test_stream_decoder()
                return die_s_("returned false", decoder);
        printf("OK\n");
 
-       printf("testing OggFLAC__stream_decoder_set_read_callback()... ");
-       if(!OggFLAC__stream_decoder_set_read_callback(decoder, stream_decoder_read_callback_))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__stream_decoder_set_write_callback()... ");
-       if(!OggFLAC__stream_decoder_set_write_callback(decoder, stream_decoder_write_callback_))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__stream_decoder_set_metadata_callback()... ");
-       if(!OggFLAC__stream_decoder_set_metadata_callback(decoder, stream_decoder_metadata_callback_))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__stream_decoder_set_error_callback()... ");
-       if(!OggFLAC__stream_decoder_set_error_callback(decoder, stream_decoder_error_callback_))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__stream_decoder_set_client_data()... ");
-       if(!OggFLAC__stream_decoder_set_client_data(decoder, &decoder_client_data))
+       printf("testing OggFLAC__stream_decoder_set_md5_checking()... ");
+       if(!OggFLAC__stream_decoder_set_md5_checking(decoder, true))
                return die_s_("returned false", decoder);
        printf("OK\n");
 
-       printf("testing OggFLAC__stream_decoder_init()... ");
-       if(OggFLAC__stream_decoder_init(decoder) != OggFLAC__STREAM_DECODER_OK)
-               return die_s_(0, decoder);
+       if(layer < LAYER_FILENAME) {
+               printf("opening Ogg FLAC file... ");
+               decoder_client_data.file = fopen(flacfilename_, "rb");
+               if(0 == decoder_client_data.file) {
+                       printf("ERROR (%s)\n", strerror(errno));
+                       return false;
+               }
+               printf("OK\n");
+       }
+
+       switch(layer) {
+               case LAYER_STREAM:
+                       printf("testing OggFLAC__stream_decoder_init_stream()... ");
+                       if(OggFLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_SEEKABLE_STREAM:
+                       printf("testing OggFLAC__stream_decoder_init_stream()... ");
+                       if(OggFLAC__stream_decoder_init_stream(decoder, stream_decoder_read_callback_, stream_decoder_seek_callback_, stream_decoder_tell_callback_, stream_decoder_length_callback_, stream_decoder_eof_callback_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILE:
+                       printf("testing OggFLAC__stream_decoder_init_FILE()... ");
+                       if(OggFLAC__stream_decoder_init_FILE(decoder, decoder_client_data.file, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing OggFLAC__stream_decoder_init_file()... ");
+                       if(OggFLAC__stream_decoder_init_file(decoder, flacfilename_, stream_decoder_write_callback_, stream_decoder_metadata_callback_, stream_decoder_error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_(0, decoder);
+                       break;
+               default:
+                       die_("internal error 009");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing OggFLAC__stream_decoder_get_state()... ");
@@ -399,10 +497,9 @@ static FLAC__bool test_stream_decoder()
        decoder_client_data.ignore_errors = false;
        decoder_client_data.error_occurred = false;
 
-       printf("opening Ogg FLAC file... ");
-       decoder_client_data.file = fopen(oggflacfilename_, "rb");
-       if(0 == decoder_client_data.file) {
-               printf("ERROR (%s)\n", strerror(errno));
+       printf("testing OggFLAC__stream_decoder_get_md5_checking()... ");
+       if(!OggFLAC__stream_decoder_get_md5_checking(decoder)) {
+               printf("FAILED, returned false, expected true\n");
                return false;
        }
        printf("OK\n");
@@ -417,23 +514,42 @@ static FLAC__bool test_stream_decoder()
                return die_s_("returned false", decoder);
        printf("OK\n");
 
-       printf("testing OggFLAC__stream_decoder_flush()... ");
-       if(!OggFLAC__stream_decoder_flush(decoder))
+       printf("testing OggFLAC__stream_decoder_skip_single_frame()... ");
+       if(!OggFLAC__stream_decoder_skip_single_frame(decoder))
                return die_s_("returned false", decoder);
        printf("OK\n");
 
-       decoder_client_data.ignore_errors = true;
-       printf("testing OggFLAC__stream_decoder_process_single()... ");
-       if(!OggFLAC__stream_decoder_process_single(decoder))
-               return die_s_("returned false", decoder);
+       if(layer < LAYER_FILE) {
+               printf("testing OggFLAC__stream_decoder_flush()... ");
+               if(!OggFLAC__stream_decoder_flush(decoder))
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+
+               decoder_client_data.ignore_errors = true;
+               printf("testing OggFLAC__stream_decoder_process_single()... ");
+               if(!OggFLAC__stream_decoder_process_single(decoder))
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
+               decoder_client_data.ignore_errors = false;
+       }
+
+       expect = (layer != LAYER_STREAM);
+       printf("testing OggFLAC__stream_decoder_seek_absolute()... ");
+       if(OggFLAC__stream_decoder_seek_absolute(decoder, 0) != expect)
+               return die_s_(expect? "returned false" : "returned true", decoder);
        printf("OK\n");
-       decoder_client_data.ignore_errors = false;
 
        printf("testing OggFLAC__stream_decoder_process_until_end_of_stream()... ");
        if(!OggFLAC__stream_decoder_process_until_end_of_stream(decoder))
                return die_s_("returned false", decoder);
        printf("OK\n");
 
+       expect = (layer != LAYER_STREAM);
+       printf("testing OggFLAC__stream_decoder_seek_absolute()... ");
+       if(OggFLAC__stream_decoder_seek_absolute(decoder, 0) != expect)
+               return die_s_(expect? "returned false" : "returned true", decoder);
+       printf("OK\n");
+
        printf("testing OggFLAC__stream_decoder_get_channels()... ");
        {
                unsigned channels = OggFLAC__stream_decoder_get_channels(decoder);
@@ -467,8 +583,10 @@ static FLAC__bool test_stream_decoder()
        printf("testing OggFLAC__stream_decoder_get_blocksize()... ");
        {
                unsigned blocksize = OggFLAC__stream_decoder_get_blocksize(decoder);
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
+               /* value could be anything since we're at the last block, so accept any reasonable answer */
+               printf("returned %u... %s\n", blocksize, blocksize>0? "OK" : "FAILED");
+               if(blocksize == 0)
+                       return false;
        }
 
        printf("testing OggFLAC__stream_decoder_get_channel_assignment()... ");
@@ -477,30 +595,35 @@ static FLAC__bool test_stream_decoder()
                printf("returned %u (%s)... OK\n", (unsigned)ca, FLAC__ChannelAssignmentString[ca]);
        }
 
-       printf("testing OggFLAC__stream_decoder_reset()... ");
-       if(!OggFLAC__stream_decoder_reset(decoder)) {
-               state = OggFLAC__stream_decoder_get_state(decoder);
-               printf("FAILED, returned false, state = %u (%s)\n", state, FLAC__StreamDecoderStateString[state]);
-               return false;
-       }
-       printf("OK\n");
+       if(layer < LAYER_FILE) {
+               printf("testing OggFLAC__stream_decoder_reset()... ");
+               if(!OggFLAC__stream_decoder_reset(decoder)) {
+                       state = OggFLAC__stream_decoder_get_state(decoder);
+                       printf("FAILED, returned false, state = %u (%s)\n", state, OggFLAC__StreamDecoderStateString[state]);
+                       return false;
+               }
+               printf("OK\n");
+
+               if(layer == LAYER_STREAM) {
+                       /* after a reset() we have to rewind the input ourselves */
+                       printf("rewinding input... ");
+                       if(fseeko(decoder_client_data.file, 0, SEEK_SET) < 0) {
+                               printf("FAILED, errno = %d\n", errno);
+                               return false;
+                       }
+                       printf("OK\n");
+               }
 
-       decoder_client_data.current_metadata_number = 0;
+               decoder_client_data.current_metadata_number = 0;
 
-       printf("rewinding input... ");
-       if(fseeko(decoder_client_data.file, 0, SEEK_SET) < 0) {
-               printf("FAILED, errno = %d\n", errno);
-               return false;
+               printf("testing OggFLAC__stream_decoder_process_until_end_of_stream()... ");
+               if(!OggFLAC__stream_decoder_process_until_end_of_stream(decoder))
+                       return die_s_("returned false", decoder);
+               printf("OK\n");
        }
-       printf("OK\n");
-
-       printf("testing OggFLAC__stream_decoder_process_until_end_of_stream()... ");
-       if(!OggFLAC__stream_decoder_process_until_end_of_stream(decoder))
-               return die_s_("returned false", decoder);
-       printf("OK\n");
 
        printf("testing OggFLAC__stream_decoder_finish()... ");
-       OggFLAC__stream_decoder_finish(decoder);
+       (void) OggFLAC__stream_decoder_finish(decoder);
        printf("OK\n");
 
        /*
@@ -789,1311 +912,37 @@ static FLAC__bool test_stream_decoder()
        if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
                return false;
 
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
+       if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
+               fclose(decoder_client_data.file);
 
        printf("testing OggFLAC__stream_decoder_delete()... ");
        OggFLAC__stream_decoder_delete(decoder);
        printf("OK\n");
 
-       fclose(decoder_client_data.file);
-
        printf("\nPASSED!\n");
 
        return true;
 }
 
-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 OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
-               case FLAC__STREAM_DECODER_READ_STATUS_ABORT:
-                       return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-               default:
-                       FLAC__ASSERT(0);
-                       return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
-       }
-}
-
-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;
-
-       (void)decoder;
-
-       if(0 == dcd) {
-               printf("ERROR: client_data in seek callback is NULL\n");
-               return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-       }
-
-       if(dcd->error_occurred)
-               return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-
-       if(fseeko(dcd->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
-               dcd->error_occurred = true;
-               return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
-       }
-
-       return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-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;
-       off_t offset;
-
-       (void)decoder;
-
-       if(0 == dcd) {
-               printf("ERROR: client_data in tell callback is NULL\n");
-               return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-       }
-
-       if(dcd->error_occurred)
-               return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-
-       offset = ftello(dcd->file);
-       *absolute_byte_offset = (FLAC__uint64)offset;
-
-       if(offset < 0) {
-               dcd->error_occurred = true;
-               return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
-       }
-
-       return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
-}
-
-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;
-
-       (void)decoder;
-
-       if(0 == dcd) {
-               printf("ERROR: client_data in length callback is NULL\n");
-               return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
-       }
-
-       if(dcd->error_occurred)
-               return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
-
-       *stream_length = (FLAC__uint64)oggflacfilesize_;
-       return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
-}
-
-static FLAC__bool seekable_stream_decoder_eof_callback_(const OggFLAC__SeekableStreamDecoder *decoder, void *client_data)
-{
-       seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data;
-
-       (void)decoder;
-
-       if(0 == dcd) {
-               printf("ERROR: client_data in eof callback is NULL\n");
-               return true;
-       }
-
-       if(dcd->error_occurred)
-               return true;
-
-       return feof(dcd->file);
-}
-
-static FLAC__StreamDecoderWriteStatus seekable_stream_decoder_write_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       (void)decoder;
-       return stream_decoder_write_callback_(0, frame, buffer, client_data);
-}
-
-static void seekable_stream_decoder_metadata_callback_(const OggFLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       (void)decoder;
-       stream_decoder_metadata_callback_(0, metadata, client_data);
-}
-
-static void seekable_stream_decoder_error_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       (void)decoder;
-       stream_decoder_error_callback_(0, status, client_data);
-}
-
-static FLAC__bool seekable_stream_decoder_test_respond_(OggFLAC__SeekableStreamDecoder *decoder, seekable_stream_decoder_client_data_struct *dcd)
+FLAC__bool test_decoders()
 {
-       if(!OggFLAC__seekable_stream_decoder_set_read_callback(decoder, seekable_stream_decoder_read_callback_))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_read_callback(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_seek_callback(decoder, seekable_stream_decoder_seek_callback_))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_seek_callback(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_tell_callback(decoder, seekable_stream_decoder_tell_callback_))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_tell_callback(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_length_callback(decoder, seekable_stream_decoder_length_callback_))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_length_callback(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_eof_callback(decoder, seekable_stream_decoder_eof_callback_))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_eof_callback(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_write_callback(decoder, seekable_stream_decoder_write_callback_))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_write_callback(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_callback(decoder, seekable_stream_decoder_metadata_callback_))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_metadata_callback(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_error_callback(decoder, seekable_stream_decoder_error_callback_))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_error_callback(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_client_data(decoder, dcd))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_client_data(), returned false", decoder);
-
-       if(!OggFLAC__seekable_stream_decoder_set_md5_checking(decoder, true))
-               return die_ss_("at OggFLAC__seekable_stream_decoder_set_md5_checking(), returned false", decoder);
-
-       printf("testing OggFLAC__seekable_stream_decoder_init()... ");
-       if(OggFLAC__seekable_stream_decoder_init(decoder) != OggFLAC__SEEKABLE_STREAM_DECODER_OK)
-               return die_ss_(0, decoder);
-       printf("OK\n");
+       init_metadata_blocks_();
+       if(!generate_file_())
+               return false;
 
-       dcd->current_metadata_number = 0;
-
-       if(fseeko(dcd->file, 0, SEEK_SET) < 0) {
-               printf("FAILED rewinding input, errno = %d\n", errno);
-               return false;
-       }
-
-       printf("testing OggFLAC__seekable_stream_decoder_process_until_end_of_stream()... ");
-       if(!OggFLAC__seekable_stream_decoder_process_until_end_of_stream(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_finish()... ");
-       (void) OggFLAC__seekable_stream_decoder_finish(decoder);
-       printf("OK\n");
-
-       return true;
-}
-
-static FLAC__bool test_seekable_stream_decoder()
-{
-       OggFLAC__SeekableStreamDecoder *decoder;
-       OggFLAC__SeekableStreamDecoderState state;
-       OggFLAC__StreamDecoderState sstate;
-       FLAC__StreamDecoderState fstate;
-       seekable_stream_decoder_client_data_struct decoder_client_data;
-
-       printf("\n+++ libOggFLAC unit test: OggFLAC__SeekableStreamDecoder\n\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_new()... ");
-       decoder = OggFLAC__seekable_stream_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_delete()... ");
-       OggFLAC__seekable_stream_decoder_delete(decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_new()... ");
-       decoder = OggFLAC__seekable_stream_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_init()... ");
-       if(OggFLAC__seekable_stream_decoder_init(decoder) == OggFLAC__SEEKABLE_STREAM_DECODER_OK)
-               return die_ss_(0, decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_delete()... ");
-       OggFLAC__seekable_stream_decoder_delete(decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-
-       printf("testing OggFLAC__seekable_stream_decoder_new()... ");
-       decoder = OggFLAC__seekable_stream_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_serial_number()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_serial_number(decoder, file_utils__serial_number))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_read_callback()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_read_callback(decoder, seekable_stream_decoder_read_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_seek_callback()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_seek_callback(decoder, seekable_stream_decoder_seek_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_tell_callback()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_tell_callback(decoder, seekable_stream_decoder_tell_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_length_callback()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_length_callback(decoder, seekable_stream_decoder_length_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_eof_callback()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_eof_callback(decoder, seekable_stream_decoder_eof_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_write_callback()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_write_callback(decoder, seekable_stream_decoder_write_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_callback()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_callback(decoder, seekable_stream_decoder_metadata_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_error_callback()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_error_callback(decoder, seekable_stream_decoder_error_callback_))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_client_data()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_client_data(decoder, &decoder_client_data))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_md5_checking()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_md5_checking(decoder, true))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_init()... ");
-       if(OggFLAC__seekable_stream_decoder_init(decoder) != OggFLAC__SEEKABLE_STREAM_DECODER_OK)
-               return die_ss_(0, decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_get_state()... ");
-       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_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);
-       printf("returned state = %u (%s)... OK\n", fstate, FLAC__StreamDecoderStateString[fstate]);
-
-       decoder_client_data.current_metadata_number = 0;
-       decoder_client_data.ignore_errors = false;
-       decoder_client_data.error_occurred = false;
-
-       printf("opening Ogg FLAC file... ");
-       decoder_client_data.file = fopen(oggflacfilename_, "rb");
-       if(0 == decoder_client_data.file) {
-               printf("ERROR (%s)\n", strerror(errno));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_get_md5_checking()... ");
-       if(!OggFLAC__seekable_stream_decoder_get_md5_checking(decoder)) {
-               printf("FAILED, returned false, expected true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_process_until_end_of_metadata()... ");
-       if(!OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_process_single()... ");
-       if(!OggFLAC__seekable_stream_decoder_process_single(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_flush()... ");
-       if(!OggFLAC__seekable_stream_decoder_flush(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       decoder_client_data.ignore_errors = true;
-       printf("testing OggFLAC__seekable_stream_decoder_process_single()... ");
-       if(!OggFLAC__seekable_stream_decoder_process_single(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-       decoder_client_data.ignore_errors = false;
-
-       printf("testing OggFLAC__seekable_stream_decoder_seek_absolute()... ");
-       if(!OggFLAC__seekable_stream_decoder_seek_absolute(decoder, 0))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_process_until_end_of_stream()... ");
-       if(!OggFLAC__seekable_stream_decoder_process_until_end_of_stream(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_get_channels()... ");
-       {
-               unsigned channels = OggFLAC__seekable_stream_decoder_get_channels(decoder);
-               if(channels != streaminfo_.data.stream_info.channels) {
-                       printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_get_bits_per_sample()... ");
-       {
-               unsigned bits_per_sample = OggFLAC__seekable_stream_decoder_get_bits_per_sample(decoder);
-               if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
-                       printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_get_sample_rate()... ");
-       {
-               unsigned sample_rate = OggFLAC__seekable_stream_decoder_get_sample_rate(decoder);
-               if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
-                       printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_get_blocksize()... ");
-       {
-               unsigned blocksize = OggFLAC__seekable_stream_decoder_get_blocksize(decoder);
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
-       }
-
-       printf("testing OggFLAC__seekable_stream_decoder_get_channel_assignment()... ");
-       {
-               FLAC__ChannelAssignment ca = OggFLAC__seekable_stream_decoder_get_channel_assignment(decoder);
-               printf("returned %u (%s)... OK\n", (unsigned)ca, FLAC__ChannelAssignmentString[ca]);
-       }
-
-       printf("testing OggFLAC__seekable_stream_decoder_reset()... ");
-       if(!OggFLAC__seekable_stream_decoder_reset(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       decoder_client_data.current_metadata_number = 0;
-
-       printf("rewinding input... ");
-       if(fseeko(decoder_client_data.file, 0, SEEK_SET) < 0) {
-               printf("FAILED, errno = %d\n", errno);
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_process_until_end_of_stream()... ");
-       if(!OggFLAC__seekable_stream_decoder_process_until_end_of_stream(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_finish()... ");
-       (void) OggFLAC__seekable_stream_decoder_finish(decoder);
-       printf("OK\n");
-
-       /*
-        * respond all
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore VORBIS_COMMENT
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore(VORBIS_COMMENT)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore(APPLICATION)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(of app block #2)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder, application2_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond VORBIS_COMMENT
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond(VORBIS_COMMENT)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond(APPLICATION)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_application(of app block #2)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_application(decoder, application2_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION, respond APPLICATION id of app#1
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore(APPLICATION)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
-        */
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_respond(APPLICATION)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_ss_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!seekable_stream_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       printf("testing OggFLAC__seekable_stream_decoder_delete()... ");
-       OggFLAC__seekable_stream_decoder_delete(decoder);
-       printf("OK\n");
-
-       fclose(decoder_client_data.file);
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-static FLAC__StreamDecoderWriteStatus file_decoder_write_callback_(const OggFLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
-{
-       (void)decoder;
-       return stream_decoder_write_callback_(0, frame, buffer, client_data);
-}
-
-static void file_decoder_metadata_callback_(const OggFLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       (void)decoder;
-       stream_decoder_metadata_callback_(0, metadata, client_data);
-}
-
-static void file_decoder_error_callback_(const OggFLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-       (void)decoder;
-       stream_decoder_error_callback_(0, status, client_data);
-}
-
-static FLAC__bool file_decoder_test_respond_(OggFLAC__FileDecoder *decoder, file_decoder_client_data_struct *dcd)
-{
-       if(!OggFLAC__file_decoder_set_write_callback(decoder, file_decoder_write_callback_))
-               return die_f_("at OggFLAC__file_decoder_set_write_callback(), returned false", decoder);
-
-       if(!OggFLAC__file_decoder_set_metadata_callback(decoder, file_decoder_metadata_callback_))
-               return die_f_("at OggFLAC__file_decoder_set_metadata_callback(), returned false", decoder);
-
-       if(!OggFLAC__file_decoder_set_error_callback(decoder, file_decoder_error_callback_))
-               return die_f_("at OggFLAC__file_decoder_set_error_callback(), returned false", decoder);
-
-       if(!OggFLAC__file_decoder_set_client_data(decoder, dcd))
-               return die_f_("at OggFLAC__file_decoder_set_client_data(), returned false", decoder);
-
-       if(!OggFLAC__file_decoder_set_filename(decoder, oggflacfilename_))
-               return die_f_("at OggFLAC__file_decoder_set_filename(), returned false", decoder);
-
-       if(!OggFLAC__file_decoder_set_md5_checking(decoder, true))
-               return die_f_("at OggFLAC__file_decoder_set_md5_checking(), returned false", decoder);
-
-       printf("testing OggFLAC__file_decoder_init()... ");
-       if(OggFLAC__file_decoder_init(decoder) != OggFLAC__FILE_DECODER_OK)
-               return die_f_(0, decoder);
-       printf("OK\n");
-
-       dcd->current_metadata_number = 0;
-
-       printf("testing OggFLAC__file_decoder_process_until_end_of_file()... ");
-       if(!OggFLAC__file_decoder_process_until_end_of_file(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_finish()... ");
-       (void) OggFLAC__file_decoder_finish(decoder);
-       printf("OK\n");
-
-       return true;
-}
-
-static FLAC__bool test_file_decoder()
-{
-       OggFLAC__FileDecoder *decoder;
-       OggFLAC__FileDecoderState state;
-       OggFLAC__SeekableStreamDecoderState ssstate;
-       OggFLAC__StreamDecoderState sstate;
-       FLAC__StreamDecoderState fstate;
-       seekable_stream_decoder_client_data_struct decoder_client_data;
-
-       printf("\n+++ libOggFLAC unit test: OggFLAC__FileDecoder\n\n");
-
-       printf("testing OggFLAC__file_decoder_new()... ");
-       decoder = OggFLAC__file_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_delete()... ");
-       OggFLAC__file_decoder_delete(decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_new()... ");
-       decoder = OggFLAC__file_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_init()... ");
-       if(OggFLAC__file_decoder_init(decoder) == OggFLAC__FILE_DECODER_OK)
-               return die_f_(0, decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_delete()... ");
-       OggFLAC__file_decoder_delete(decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-
-       printf("testing OggFLAC__file_decoder_new()... ");
-       decoder = OggFLAC__file_decoder_new();
-       if(0 == decoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_serial_number()... ");
-       if(!OggFLAC__file_decoder_set_serial_number(decoder, file_utils__serial_number))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_write_callback()... ");
-       if(!OggFLAC__file_decoder_set_write_callback(decoder, file_decoder_write_callback_))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_callback()... ");
-       if(!OggFLAC__file_decoder_set_metadata_callback(decoder, file_decoder_metadata_callback_))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_error_callback()... ");
-       if(!OggFLAC__file_decoder_set_error_callback(decoder, file_decoder_error_callback_))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_client_data()... ");
-       if(!OggFLAC__file_decoder_set_client_data(decoder, &decoder_client_data))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_filename()... ");
-       if(!OggFLAC__file_decoder_set_filename(decoder, oggflacfilename_))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_md5_checking()... ");
-       if(!OggFLAC__file_decoder_set_md5_checking(decoder, true))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_init()... ");
-       if(OggFLAC__file_decoder_init(decoder) != OggFLAC__FILE_DECODER_OK)
-               return die_f_(0, decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_get_state()... ");
-       state = OggFLAC__file_decoder_get_state(decoder);
-       printf("returned state = %u (%s)... OK\n", state, OggFLAC__FileDecoderStateString[state]);
-
-       printf("testing OggFLAC__file_decoder_get_seekable_stream_decoder_state()... ");
-       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_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);
-       printf("returned state = %u (%s)... OK\n", fstate, FLAC__StreamDecoderStateString[fstate]);
-
-       decoder_client_data.current_metadata_number = 0;
-       decoder_client_data.ignore_errors = false;
-       decoder_client_data.error_occurred = false;
-
-       printf("testing OggFLAC__file_decoder_get_md5_checking()... ");
-       if(!OggFLAC__file_decoder_get_md5_checking(decoder)) {
-               printf("FAILED, returned false, expected true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_process_until_end_of_metadata()... ");
-       if(!OggFLAC__file_decoder_process_until_end_of_metadata(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_process_single()... ");
-       if(!OggFLAC__file_decoder_process_single(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_seek_absolute()... ");
-       if(!OggFLAC__file_decoder_seek_absolute(decoder, 0))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_process_until_end_of_file()... ");
-       if(!OggFLAC__file_decoder_process_until_end_of_file(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_get_channels()... ");
-       {
-               unsigned channels = OggFLAC__file_decoder_get_channels(decoder);
-               if(channels != streaminfo_.data.stream_info.channels) {
-                       printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_get_bits_per_sample()... ");
-       {
-               unsigned bits_per_sample = OggFLAC__file_decoder_get_bits_per_sample(decoder);
-               if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
-                       printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_get_sample_rate()... ");
-       {
-               unsigned sample_rate = OggFLAC__file_decoder_get_sample_rate(decoder);
-               if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
-                       printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
-                       return false;
-               }
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_get_blocksize()... ");
-       {
-               unsigned blocksize = OggFLAC__file_decoder_get_blocksize(decoder);
-               /* value could be anything since we're at the last block, so accept any answer */
-               printf("returned %u... OK\n", blocksize);
-       }
-
-       printf("testing OggFLAC__file_decoder_get_channel_assignment()... ");
-       {
-               FLAC__ChannelAssignment ca = OggFLAC__file_decoder_get_channel_assignment(decoder);
-               printf("returned %u (%s)... OK\n", (unsigned)ca, FLAC__ChannelAssignmentString[ca]);
-       }
-
-       printf("testing OggFLAC__file_decoder_finish()... ");
-       (void) OggFLAC__file_decoder_finish(decoder);
-       printf("OK\n");
-
-       /*
-        * respond all
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore VORBIS_COMMENT
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore(VORBIS_COMMENT)... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore(APPLICATION)... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_application(of app block #2)... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_application(decoder, application2_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond VORBIS_COMMENT
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond(VORBIS_COMMENT)... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond(APPLICATION)... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION id of app#1 & app#2
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_application(of app block #2)... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_application(decoder, application2_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * respond all, ignore APPLICATION, respond APPLICATION id of app#1
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore(APPLICATION)... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond_application(of app block #1)... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /*
-        * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
-        */
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_all()... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_all(decoder))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_respond(APPLICATION)... ");
-       if(!OggFLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_APPLICATION))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_decoder_set_metadata_ignore_application(of app block #1)... ");
-       if(!OggFLAC__file_decoder_set_metadata_ignore_application(decoder, application1_.data.application.id))
-               return die_f_("returned false", decoder);
-       printf("OK\n");
-
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-
-       if(!file_decoder_test_respond_(decoder, &decoder_client_data))
-               return false;
-
-       /* done, now leave the sequence the way we found it... */
-       num_expected_ = 0;
-       expected_metadata_sequence_[num_expected_++] = &streaminfo_;
-       expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
-       expected_metadata_sequence_[num_expected_++] = &padding_;
-       expected_metadata_sequence_[num_expected_++] = &seektable_;
-       expected_metadata_sequence_[num_expected_++] = &application1_;
-       expected_metadata_sequence_[num_expected_++] = &application2_;
-       expected_metadata_sequence_[num_expected_++] = &cuesheet_;
-       expected_metadata_sequence_[num_expected_++] = &unknown_;
-
-       printf("testing OggFLAC__file_decoder_delete()... ");
-       OggFLAC__file_decoder_delete(decoder);
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-FLAC__bool test_decoders()
-{
-       init_metadata_blocks_();
-       if(!generate_file_())
+       if(!test_stream_decoder(LAYER_STREAM))
                return false;
 
-       if(!test_stream_decoder())
+       if(!test_stream_decoder(LAYER_SEEKABLE_STREAM))
                return false;
 
-       if(!test_seekable_stream_decoder())
+       if(!test_stream_decoder(LAYER_FILE))
                return false;
 
-       if(!test_file_decoder())
+       if(!test_stream_decoder(LAYER_FILENAME))
                return false;
 
-       (void) grabbag__file_remove_file(oggflacfilename_);
+       (void) grabbag__file_remove_file(flacfilename_);
        free_metadata_blocks_();
 
        return true;
index cd0f1db..871ead4 100644 (file)
 #  include <config.h>
 #endif
 
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include "encoders.h"
-#include "file_utils.h"
-#include "metadata_utils.h"
 #include "FLAC/assert.h"
-#include "OggFLAC/file_encoder.h"
-#include "OggFLAC/seekable_stream_encoder.h"
 #include "OggFLAC/stream_encoder.h"
 #include "share/grabbag.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include "test_libs_common/file_utils_oggflac.h"
+#include "test_libs_common/metadata_utils.h"
+
+typedef enum {
+       LAYER_STREAM = 0, /* FLAC__stream_encoder_init_stream() without seeking */
+       LAYER_SEEKABLE_STREAM, /* FLAC__stream_encoder_init_stream() with seeking */
+       LAYER_FILE, /* FLAC__stream_encoder_init_FILE() */
+       LAYER_FILENAME /* FLAC__stream_encoder_init_file() */
+} Layer;
+
+static const char * const LayerString[] = {
+       "Stream",
+       "Seekable Stream",
+       "FILE*",
+       "Filename"
+};
 
 static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
 static FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &unknown_ };
 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
-static const char *oggflacfilename_ = "metadata.ogg";
+static const char *flacfilename_ = "metadata.ogg";
+
+static FLAC__bool die_(const char *msg)
+{
+       printf("ERROR: %s\n", msg);
+       return false;
+}
 
 static FLAC__bool die_s_(const char *msg, const OggFLAC__StreamEncoder *encoder)
 {
@@ -59,89 +78,66 @@ static FLAC__bool die_s_(const char *msg, const OggFLAC__StreamEncoder *encoder)
        return false;
 }
 
-static FLAC__bool die_ss_(const char *msg, const OggFLAC__SeekableStreamEncoder *encoder)
+static void init_metadata_blocks_()
 {
-       OggFLAC__SeekableStreamEncoderState state = OggFLAC__seekable_stream_encoder_get_state(encoder);
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)state, OggFLAC__SeekableStreamEncoderStateString[state]);
-       if(state == OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) {
-               FLAC__StreamEncoderState state_ = OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(encoder);
-               printf("      FLAC stream encoder state = %u (%s)\n", (unsigned)state_, FLAC__StreamEncoderStateString[state_]);
-               if(state_ == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                       FLAC__StreamDecoderState dstate = OggFLAC__seekable_stream_encoder_get_verify_decoder_state(encoder);
-                       printf("      verify decoder state = %u (%s)\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]);
-               }
-       }
-
-       return false;
+       mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
 }
 
-static FLAC__bool die_f_(const char *msg, const OggFLAC__FileEncoder *encoder)
+static void free_metadata_blocks_()
 {
-       OggFLAC__FileEncoderState state = OggFLAC__file_encoder_get_state(encoder);
-
-       if(msg)
-               printf("FAILED, %s", msg);
-       else
-               printf("FAILED");
-
-       printf(", state = %u (%s)\n", (unsigned)state, OggFLAC__SeekableStreamEncoderStateString[state]);
-       if(state == OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR) {
-               OggFLAC__SeekableStreamEncoderState state_ = OggFLAC__file_encoder_get_seekable_stream_encoder_state(encoder);
-               printf("      seekable stream encoder state = %u (%s)\n", (unsigned)state_, OggFLAC__SeekableStreamEncoderStateString[state_]);
-               if(state_ == OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) {
-                       FLAC__StreamEncoderState state__ = OggFLAC__file_encoder_get_FLAC_stream_encoder_state(encoder);
-                       printf("      FLAC stream encoder state = %u (%s)\n", (unsigned)state__, FLAC__StreamEncoderStateString[state__]);
-                       if(state__ == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
-                               FLAC__StreamDecoderState dstate = OggFLAC__file_encoder_get_verify_decoder_state(encoder);
-                               printf("      verify decoder state = %u (%s)\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]);
-                       }
-               }
-       }
+       mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+}
 
-       return false;
+static OggFLAC__StreamEncoderReadStatus stream_encoder_read_callback_(const OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+       (void)encoder, (void)buffer, (void)bytes, (void)client_data;
+       memset(buffer, 0, *bytes); /* init buffer to avoid valgrind errors */
+       return OggFLAC__STREAM_ENCODER_READ_STATUS_CONTINUE;
 }
 
-static void init_metadata_blocks_()
+static FLAC__StreamEncoderWriteStatus stream_encoder_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
 {
-       mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+       (void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
+       return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
 }
 
-static void free_metadata_blocks_()
+static FLAC__StreamEncoderSeekStatus stream_encoder_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
 {
-       mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+       (void)encoder, (void)absolute_byte_offset, (void)client_data;
+       return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
 }
 
-static FLAC__StreamEncoderWriteStatus stream_encoder_write_callback_(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
+static FLAC__StreamEncoderTellStatus stream_encoder_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
 {
-       (void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
-       return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+       (void)encoder, (void)client_data;
+       *absolute_byte_offset = 0;
+       return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
 }
 
-static void stream_encoder_metadata_callback_(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
+static void stream_encoder_metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        (void)encoder, (void)metadata, (void)client_data;
 }
 
+static void stream_encoder_progress_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
+{
+       (void)encoder, (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate, (void)client_data;
+}
 
-static FLAC__bool test_stream_encoder()
+static FLAC__bool test_stream_encoder(Layer layer)
 {
        OggFLAC__StreamEncoder *encoder;
        OggFLAC__StreamEncoderState state;
        FLAC__StreamEncoderState fstate;
        FLAC__StreamDecoderState dstate;
+       FILE *file = 0;
        FLAC__int32 samples[1024];
        FLAC__int32 *samples_array[1];
        unsigned i;
 
        samples_array[0] = samples;
 
-       printf("\n+++ libOggFLAC unit test: OggFLAC__StreamEncoder\n\n");
+       printf("\n+++ libOggFLAC unit test: OggFLAC__StreamEncoder (layer: %s)\n\n", LayerString[layer]);
 
        printf("testing OggFLAC__stream_encoder_new()... ");
        encoder = OggFLAC__stream_encoder_new();
@@ -246,24 +242,39 @@ static FLAC__bool test_stream_encoder()
                return die_s_("returned false", encoder);
        printf("OK\n");
 
-       printf("testing OggFLAC__stream_encoder_set_write_callback()... ");
-       if(!OggFLAC__stream_encoder_set_write_callback(encoder, stream_encoder_write_callback_))
-               return die_s_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__stream_encoder_set_metadata_callback()... ");
-       if(!OggFLAC__stream_encoder_set_metadata_callback(encoder, stream_encoder_metadata_callback_))
-               return die_s_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__stream_encoder_set_client_data()... ");
-       if(!OggFLAC__stream_encoder_set_client_data(encoder, 0))
-               return die_s_("returned false", encoder);
-       printf("OK\n");
+       switch(layer) {
+               case LAYER_STREAM:
+                       printf("testing OggFLAC__stream_encoder_init_stream()... ");
+                       if(OggFLAC__stream_encoder_init_stream(encoder, /*read_callback=*/0, stream_encoder_write_callback_, /*seek_callback=*/0, /*tell_callback=*/0, stream_encoder_metadata_callback_, /*client_data=*/0) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_SEEKABLE_STREAM:
+                       printf("testing OggFLAC__stream_encoder_init_stream()... ");
+                       if(OggFLAC__stream_encoder_init_stream(encoder, stream_encoder_read_callback_, stream_encoder_write_callback_, stream_encoder_seek_callback_, stream_encoder_tell_callback_, /*metadata_callback=*/0, /*client_data=*/0) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_FILE:
+                       printf("opening file for Ogg FLAC output... ");
+                       file = fopen(flacfilename_, "w+b");
+                       if(0 == file) {
+                               printf("ERROR (%s)\n", strerror(errno));
+                               return false;
+                       }
+                       printf("OK\n");
 
-       printf("testing OggFLAC__stream_encoder_init()... ");
-       if(OggFLAC__stream_encoder_init(encoder) != FLAC__STREAM_ENCODER_OK)
-               return die_s_(0, encoder);
+                       printf("testing OggFLAC__stream_encoder_init_FILE()... ");
+                       if(OggFLAC__stream_encoder_init_FILE(encoder, file, stream_encoder_progress_callback_, /*client_data=*/0) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               case LAYER_FILENAME:
+                       printf("testing OggFLAC__stream_encoder_init_file()... ");
+                       if(OggFLAC__stream_encoder_init_file(encoder, flacfilename_, stream_encoder_progress_callback_, /*client_data=*/0) != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
+                               return die_s_(0, encoder);
+                       break;
+               default:
+                       die_("internal error 001");
+                       return false;
+       }
        printf("OK\n");
 
        printf("testing OggFLAC__stream_encoder_get_state()... ");
@@ -435,678 +446,23 @@ static FLAC__bool test_stream_encoder()
        return true;
 }
 
-OggFLAC__SeekableStreamEncoderReadStatus seekable_stream_encoder_read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
-{
-       (void)encoder, (void)buffer, (void)bytes, (void)client_data;
-       memset(buffer, 0, *bytes); /* init buffer to avoid valgrind errors */
-       return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE;
-}
-
-FLAC__SeekableStreamEncoderSeekStatus seekable_stream_encoder_seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
-{
-       (void)encoder, (void)absolute_byte_offset, (void)client_data;
-       return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
-}
-
-FLAC__SeekableStreamEncoderTellStatus seekable_stream_encoder_tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
-{
-       (void)encoder, (void)client_data;
-       *absolute_byte_offset = 0;
-       return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK;
-}
-
-FLAC__StreamEncoderWriteStatus seekable_stream_encoder_write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       (void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
-       return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-}
-
-static FLAC__bool test_seekable_stream_encoder()
-{
-       OggFLAC__SeekableStreamEncoder *encoder;
-       OggFLAC__SeekableStreamEncoderState state;
-       FLAC__StreamEncoderState fstate;
-       FLAC__StreamDecoderState dstate;
-       FLAC__int32 samples[1024];
-       FLAC__int32 *samples_array[1];
-       unsigned i;
-
-       samples_array[0] = samples;
-
-       printf("\n+++ libOggFLAC unit test: OggFLAC__SeekableStreamEncoder\n\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_new()... ");
-       encoder = OggFLAC__seekable_stream_encoder_new();
-       if(0 == encoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_serial_number()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_serial_number(encoder, file_utils__serial_number))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_verify()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_verify(encoder, true))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_streamable_subset()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_streamable_subset(encoder, true))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_channels()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_channels(encoder, streaminfo_.data.stream_info.channels))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_bits_per_sample()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_bits_per_sample(encoder, streaminfo_.data.stream_info.bits_per_sample))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_sample_rate()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_sample_rate(encoder, streaminfo_.data.stream_info.sample_rate))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_blocksize()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_blocksize(encoder, streaminfo_.data.stream_info.min_blocksize))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_max_lpc_order()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_max_lpc_order(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_do_escape_coding()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_do_escape_coding(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder, false))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_min_residual_partition_order()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_max_residual_partition_order()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_total_samples_estimate()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_total_samples_estimate(encoder, streaminfo_.data.stream_info.total_samples))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_metadata()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_metadata(encoder, metadata_sequence_, num_metadata_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_read_callback()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_read_callback(encoder, seekable_stream_encoder_read_callback_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_seek_callback()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_seek_callback(encoder, seekable_stream_encoder_seek_callback_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_tell_callback()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_tell_callback(encoder, seekable_stream_encoder_tell_callback_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_write_callback()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_write_callback(encoder, seekable_stream_encoder_write_callback_))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_set_client_data()... ");
-       if(!OggFLAC__seekable_stream_encoder_set_client_data(encoder, 0))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_init()... ");
-       if(OggFLAC__seekable_stream_encoder_init(encoder) != OggFLAC__SEEKABLE_STREAM_ENCODER_OK)
-               return die_ss_(0, encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_state()... ");
-       state = OggFLAC__seekable_stream_encoder_get_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)state, OggFLAC__SeekableStreamEncoderStateString[state]);
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state()... ");
-       fstate = OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)fstate, FLAC__StreamEncoderStateString[fstate]);
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_verify_decoder_state()... ");
-       dstate = OggFLAC__seekable_stream_encoder_get_verify_decoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]);
-
-       {
-               FLAC__uint64 absolute_sample;
-               unsigned frame_number;
-               unsigned channel;
-               unsigned sample;
-               FLAC__int32 expected;
-               FLAC__int32 got;
-
-               printf("testing OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats()... ");
-               OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               printf("OK\n");
-       }
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_verify()... ");
-       if(OggFLAC__seekable_stream_encoder_get_verify(encoder) != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_streamable_subset()... ");
-       if(OggFLAC__seekable_stream_encoder_get_streamable_subset(encoder) != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo()... ");
-       if(OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo()... ");
-       if(OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_channels()... ");
-       if(OggFLAC__seekable_stream_encoder_get_channels(encoder) != streaminfo_.data.stream_info.channels) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, OggFLAC__seekable_stream_encoder_get_channels(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_bits_per_sample()... ");
-       if(OggFLAC__seekable_stream_encoder_get_bits_per_sample(encoder) != streaminfo_.data.stream_info.bits_per_sample) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, OggFLAC__seekable_stream_encoder_get_bits_per_sample(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_sample_rate()... ");
-       if(OggFLAC__seekable_stream_encoder_get_sample_rate(encoder) != streaminfo_.data.stream_info.sample_rate) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, OggFLAC__seekable_stream_encoder_get_sample_rate(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_blocksize()... ");
-       if(OggFLAC__seekable_stream_encoder_get_blocksize(encoder) != streaminfo_.data.stream_info.min_blocksize) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, OggFLAC__seekable_stream_encoder_get_blocksize(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_max_lpc_order()... ");
-       if(OggFLAC__seekable_stream_encoder_get_max_lpc_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, OggFLAC__seekable_stream_encoder_get_max_lpc_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision()... ");
-       (void)OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder);
-       /* we asked the encoder to auto select this so we accept anything */
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search()... ");
-       if(OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_do_escape_coding()... ");
-       if(OggFLAC__seekable_stream_encoder_get_do_escape_coding(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search()... ");
-       if(OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_min_residual_partition_order()... ");
-       if(OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_max_residual_partition_order()... ");
-       if(OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist()... ");
-       if(OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_get_total_samples_estimate()... ");
-       if(OggFLAC__seekable_stream_encoder_get_total_samples_estimate(encoder) != streaminfo_.data.stream_info.total_samples) {
-               printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, OggFLAC__seekable_stream_encoder_get_total_samples_estimate(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       printf("testing OggFLAC__seekable_stream_encoder_process()... ");
-       if(!OggFLAC__seekable_stream_encoder_process(encoder, (const FLAC__int32 * const *)samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_process_interleaved()... ");
-       if(!OggFLAC__seekable_stream_encoder_process_interleaved(encoder, samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return die_ss_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_finish()... ");
-       OggFLAC__seekable_stream_encoder_finish(encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__seekable_stream_encoder_delete()... ");
-       OggFLAC__seekable_stream_encoder_delete(encoder);
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
-static void file_encoder_progress_callback_(const OggFLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
-{
-       (void)encoder, (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate, (void)client_data;
-}
-
-static FLAC__bool test_file_encoder()
-{
-       OggFLAC__FileEncoder *encoder;
-       OggFLAC__FileEncoderState state;
-       OggFLAC__SeekableStreamEncoderState sstate;
-       FLAC__StreamEncoderState fstate;
-       FLAC__StreamDecoderState dstate;
-       FLAC__int32 samples[1024];
-       FLAC__int32 *samples_array[1];
-       unsigned i;
-
-       samples_array[0] = samples;
-
-       printf("\n+++ libOggFLAC unit test: OggFLAC__FileEncoder\n\n");
-
-       printf("testing OggFLAC__file_encoder_new()... ");
-       encoder = OggFLAC__file_encoder_new();
-       if(0 == encoder) {
-               printf("FAILED, returned NULL\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_serial_number()... ");
-       if(!OggFLAC__file_encoder_set_serial_number(encoder, file_utils__serial_number))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_verify()... ");
-       if(!OggFLAC__file_encoder_set_verify(encoder, true))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_streamable_subset()... ");
-       if(!OggFLAC__file_encoder_set_streamable_subset(encoder, true))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_do_mid_side_stereo()... ");
-       if(!OggFLAC__file_encoder_set_do_mid_side_stereo(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_loose_mid_side_stereo()... ");
-       if(!OggFLAC__file_encoder_set_loose_mid_side_stereo(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_channels()... ");
-       if(!OggFLAC__file_encoder_set_channels(encoder, streaminfo_.data.stream_info.channels))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_bits_per_sample()... ");
-       if(!OggFLAC__file_encoder_set_bits_per_sample(encoder, streaminfo_.data.stream_info.bits_per_sample))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_sample_rate()... ");
-       if(!OggFLAC__file_encoder_set_sample_rate(encoder, streaminfo_.data.stream_info.sample_rate))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_blocksize()... ");
-       if(!OggFLAC__file_encoder_set_blocksize(encoder, streaminfo_.data.stream_info.min_blocksize))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_max_lpc_order()... ");
-       if(!OggFLAC__file_encoder_set_max_lpc_order(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_qlp_coeff_precision()... ");
-       if(!OggFLAC__file_encoder_set_qlp_coeff_precision(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_do_qlp_coeff_prec_search()... ");
-       if(!OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_do_escape_coding()... ");
-       if(!OggFLAC__file_encoder_set_do_escape_coding(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_do_exhaustive_model_search()... ");
-       if(!OggFLAC__file_encoder_set_do_exhaustive_model_search(encoder, false))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_min_residual_partition_order()... ");
-       if(!OggFLAC__file_encoder_set_min_residual_partition_order(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_max_residual_partition_order()... ");
-       if(!OggFLAC__file_encoder_set_max_residual_partition_order(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_rice_parameter_search_dist()... ");
-       if(!OggFLAC__file_encoder_set_rice_parameter_search_dist(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_total_samples_estimate()... ");
-       if(!OggFLAC__file_encoder_set_total_samples_estimate(encoder, streaminfo_.data.stream_info.total_samples))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_metadata()... ");
-       if(!OggFLAC__file_encoder_set_metadata(encoder, metadata_sequence_, num_metadata_))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_filename()... ");
-       if(!OggFLAC__file_encoder_set_filename(encoder, oggflacfilename_))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_progress_callback()... ");
-       if(!OggFLAC__file_encoder_set_progress_callback(encoder, file_encoder_progress_callback_))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_set_client_data()... ");
-       if(!OggFLAC__file_encoder_set_client_data(encoder, 0))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_init()... ");
-       if(OggFLAC__file_encoder_init(encoder) != OggFLAC__FILE_ENCODER_OK)
-               return die_f_(0, encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_state()... ");
-       state = OggFLAC__file_encoder_get_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)state, OggFLAC__FileEncoderStateString[state]);
-
-       printf("testing OggFLAC__file_encoder_get_seekable_stream_encoder_state()... ");
-       sstate = OggFLAC__file_encoder_get_seekable_stream_encoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)sstate, OggFLAC__SeekableStreamEncoderStateString[sstate]);
-
-       printf("testing OggFLAC__file_encoder_get_FLAC_stream_encoder_state()... ");
-       fstate = OggFLAC__file_encoder_get_FLAC_stream_encoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)fstate, FLAC__StreamEncoderStateString[fstate]);
-
-       printf("testing OggFLAC__file_encoder_get_verify_decoder_state()... ");
-       dstate = OggFLAC__file_encoder_get_verify_decoder_state(encoder);
-       printf("returned state = %u (%s)... OK\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]);
-
-       {
-               FLAC__uint64 absolute_sample;
-               unsigned frame_number;
-               unsigned channel;
-               unsigned sample;
-               FLAC__int32 expected;
-               FLAC__int32 got;
-
-               printf("testing OggFLAC__file_encoder_get_verify_decoder_error_stats()... ");
-               OggFLAC__file_encoder_get_verify_decoder_error_stats(encoder, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
-               printf("OK\n");
-       }
-
-       printf("testing OggFLAC__file_encoder_get_verify()... ");
-       if(OggFLAC__file_encoder_get_verify(encoder) != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_streamable_subset()... ");
-       if(OggFLAC__file_encoder_get_streamable_subset(encoder) != true) {
-               printf("FAILED, expected true, got false\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_do_mid_side_stereo()... ");
-       if(OggFLAC__file_encoder_get_do_mid_side_stereo(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_loose_mid_side_stereo()... ");
-       if(OggFLAC__file_encoder_get_loose_mid_side_stereo(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_channels()... ");
-       if(OggFLAC__file_encoder_get_channels(encoder) != streaminfo_.data.stream_info.channels) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, OggFLAC__file_encoder_get_channels(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_bits_per_sample()... ");
-       if(OggFLAC__file_encoder_get_bits_per_sample(encoder) != streaminfo_.data.stream_info.bits_per_sample) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, OggFLAC__file_encoder_get_bits_per_sample(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_sample_rate()... ");
-       if(OggFLAC__file_encoder_get_sample_rate(encoder) != streaminfo_.data.stream_info.sample_rate) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, OggFLAC__file_encoder_get_sample_rate(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_blocksize()... ");
-       if(OggFLAC__file_encoder_get_blocksize(encoder) != streaminfo_.data.stream_info.min_blocksize) {
-               printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, OggFLAC__file_encoder_get_blocksize(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_max_lpc_order()... ");
-       if(OggFLAC__file_encoder_get_max_lpc_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, OggFLAC__file_encoder_get_max_lpc_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_qlp_coeff_precision()... ");
-       (void)OggFLAC__file_encoder_get_qlp_coeff_precision(encoder);
-       /* we asked the encoder to auto select this so we accept anything */
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_do_qlp_coeff_prec_search()... ");
-       if(OggFLAC__file_encoder_get_do_qlp_coeff_prec_search(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_do_escape_coding()... ");
-       if(OggFLAC__file_encoder_get_do_escape_coding(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_do_exhaustive_model_search()... ");
-       if(OggFLAC__file_encoder_get_do_exhaustive_model_search(encoder) != false) {
-               printf("FAILED, expected false, got true\n");
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_min_residual_partition_order()... ");
-       if(OggFLAC__file_encoder_get_min_residual_partition_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, OggFLAC__file_encoder_get_min_residual_partition_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_max_residual_partition_order()... ");
-       if(OggFLAC__file_encoder_get_max_residual_partition_order(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, OggFLAC__file_encoder_get_max_residual_partition_order(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_rice_parameter_search_dist()... ");
-       if(OggFLAC__file_encoder_get_rice_parameter_search_dist(encoder) != 0) {
-               printf("FAILED, expected %u, got %u\n", 0, OggFLAC__file_encoder_get_rice_parameter_search_dist(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_get_total_samples_estimate()... ");
-       if(OggFLAC__file_encoder_get_total_samples_estimate(encoder) != streaminfo_.data.stream_info.total_samples) {
-               printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, OggFLAC__file_encoder_get_total_samples_estimate(encoder));
-               return false;
-       }
-       printf("OK\n");
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       printf("testing OggFLAC__file_encoder_process()... ");
-       if(!OggFLAC__file_encoder_process(encoder, (const FLAC__int32 * const *)samples_array, sizeof(samples) / sizeof(FLAC__int32)))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_process_interleaved()... ");
-       if(!OggFLAC__file_encoder_process_interleaved(encoder, samples, sizeof(samples) / sizeof(FLAC__int32)))
-               return die_f_("returned false", encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_finish()... ");
-       OggFLAC__file_encoder_finish(encoder);
-       printf("OK\n");
-
-       printf("testing OggFLAC__file_encoder_delete()... ");
-       OggFLAC__file_encoder_delete(encoder);
-       printf("OK\n");
-
-       printf("\nPASSED!\n");
-
-       return true;
-}
-
 FLAC__bool test_encoders()
 {
        init_metadata_blocks_();
 
-       if(!test_stream_encoder())
+       if(!test_stream_encoder(LAYER_STREAM))
+               return false;
+
+       if(!test_stream_encoder(LAYER_SEEKABLE_STREAM))
                return false;
 
-       if(!test_seekable_stream_encoder())
+       if(!test_stream_encoder(LAYER_FILE))
                return false;
 
-       if(!test_file_encoder())
+       if(!test_stream_encoder(LAYER_FILENAME))
                return false;
 
-       (void) grabbag__file_remove_file(oggflacfilename_);
+       (void) grabbag__file_remove_file(flacfilename_);
        free_metadata_blocks_();
 
        return true;
diff --git a/src/test_libOggFLAC/file_utils.c b/src/test_libOggFLAC/file_utils.c
deleted file mode 100644 (file)
index d397b5b..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/* test_libOggFLAC - Unit tester for libOggFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "file_utils.h"
-#include "FLAC/assert.h"
-#include "OggFLAC/stream_encoder.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h> /* for stat() */
-
-#ifdef min
-#undef min
-#endif
-#define min(a,b) ((a)<(b)?(a):(b))
-
-const long file_utils__serial_number = 12345;
-
-#ifdef FLAC__VALGRIND_TESTING
-static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
-       size_t ret = fwrite(ptr, size, nmemb, stream);
-       if(!ferror(stream))
-               fflush(stream);
-       return ret;
-}
-#else
-#define local__fwrite fwrite
-#endif
-
-typedef struct {
-       FILE *file;
-} encoder_client_struct;
-
-static FLAC__StreamEncoderWriteStatus encoder_write_callback_(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
-{
-       encoder_client_struct *ecd = (encoder_client_struct*)client_data;
-
-       (void)encoder, (void)samples, (void)current_frame;
-
-       if(local__fwrite(buffer, 1, bytes, ecd->file) != bytes)
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
-       else
-               return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-}
-
-static void encoder_metadata_callback_(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-       (void)encoder, (void)metadata, (void)client_data;
-}
-
-FLAC__bool file_utils__generate_oggflacfile(const char *output_filename, off_t *output_filesize, unsigned length, const FLAC__StreamMetadata *streaminfo, FLAC__StreamMetadata **metadata, unsigned num_metadata)
-{
-       FLAC__int32 samples[1024];
-       OggFLAC__StreamEncoder *encoder;
-       encoder_client_struct encoder_client_data;
-       unsigned i, n;
-
-       FLAC__ASSERT(0 != output_filename);
-       FLAC__ASSERT(0 != streaminfo);
-       FLAC__ASSERT(streaminfo->type == FLAC__METADATA_TYPE_STREAMINFO);
-       FLAC__ASSERT((streaminfo->is_last && num_metadata == 0) || (!streaminfo->is_last && num_metadata > 0));
-
-       if(0 == (encoder_client_data.file = fopen(output_filename, "wb")))
-               return false;
-
-       encoder = OggFLAC__stream_encoder_new();
-       if(0 == encoder) {
-               fclose(encoder_client_data.file);
-               return false;
-       }
-
-       OggFLAC__stream_encoder_set_serial_number(encoder, file_utils__serial_number);
-       OggFLAC__stream_encoder_set_verify(encoder, true);
-       OggFLAC__stream_encoder_set_streamable_subset(encoder, true);
-       OggFLAC__stream_encoder_set_do_mid_side_stereo(encoder, false);
-       OggFLAC__stream_encoder_set_loose_mid_side_stereo(encoder, false);
-       OggFLAC__stream_encoder_set_channels(encoder, streaminfo->data.stream_info.channels);
-       OggFLAC__stream_encoder_set_bits_per_sample(encoder, streaminfo->data.stream_info.bits_per_sample);
-       OggFLAC__stream_encoder_set_sample_rate(encoder, streaminfo->data.stream_info.sample_rate);
-       OggFLAC__stream_encoder_set_blocksize(encoder, streaminfo->data.stream_info.min_blocksize);
-       OggFLAC__stream_encoder_set_max_lpc_order(encoder, 0);
-       OggFLAC__stream_encoder_set_qlp_coeff_precision(encoder, 0);
-       OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, false);
-       OggFLAC__stream_encoder_set_do_escape_coding(encoder, false);
-       OggFLAC__stream_encoder_set_do_exhaustive_model_search(encoder, false);
-       OggFLAC__stream_encoder_set_min_residual_partition_order(encoder, 0);
-       OggFLAC__stream_encoder_set_max_residual_partition_order(encoder, 0);
-       OggFLAC__stream_encoder_set_rice_parameter_search_dist(encoder, 0);
-       OggFLAC__stream_encoder_set_total_samples_estimate(encoder, streaminfo->data.stream_info.total_samples);
-       OggFLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
-       OggFLAC__stream_encoder_set_write_callback(encoder, encoder_write_callback_);
-       OggFLAC__stream_encoder_set_metadata_callback(encoder, encoder_metadata_callback_);
-       OggFLAC__stream_encoder_set_client_data(encoder, &encoder_client_data);
-
-       if(OggFLAC__stream_encoder_init(encoder) != OggFLAC__STREAM_ENCODER_OK) {
-               fclose(encoder_client_data.file);
-               return false;
-       }
-
-       /* init the dummy sample buffer */
-       for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
-               samples[i] = i & 7;
-
-       while(length > 0) {
-               n = min(length, sizeof(samples) / sizeof(FLAC__int32));
-
-               if(!OggFLAC__stream_encoder_process_interleaved(encoder, samples, n)) {
-                       fclose(encoder_client_data.file);
-                       return false;
-               }
-
-               length -= n;
-       }
-
-       OggFLAC__stream_encoder_finish(encoder);
-
-       fclose(encoder_client_data.file);
-
-       OggFLAC__stream_encoder_delete(encoder);
-
-       if(0 != output_filesize) {
-               struct stat filestats;
-
-               if(stat(output_filename, &filestats) != 0)
-                       return false;
-               else
-                       *output_filesize = filestats.st_size;
-       }
-
-       return true;
-}
diff --git a/src/test_libOggFLAC/metadata_utils.c b/src/test_libOggFLAC/metadata_utils.c
deleted file mode 100644 (file)
index c866982..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-/* test_libFLAC - Unit tester for libFLAC
- * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * These are not tests, just utility functions used by the metadata tests
- */
-
-#if HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "metadata_utils.h"
-#include "FLAC/metadata.h"
-#include <stdio.h>
-#include <stdlib.h> /* for malloc() */
-#include <string.h> /* for memcmp() */
-
-FLAC__bool mutils__compare_block_data_streaminfo(const FLAC__StreamMetadata_StreamInfo *block, const FLAC__StreamMetadata_StreamInfo *blockcopy)
-{
-       if(blockcopy->min_blocksize != block->min_blocksize) {
-               printf("FAILED, min_blocksize mismatch, expected %u, got %u\n", block->min_blocksize, blockcopy->min_blocksize);
-               return false;
-       }
-       if(blockcopy->max_blocksize != block->max_blocksize) {
-               printf("FAILED, max_blocksize mismatch, expected %u, got %u\n", block->max_blocksize, blockcopy->max_blocksize);
-               return false;
-       }
-       if(blockcopy->min_framesize != block->min_framesize) {
-               printf("FAILED, min_framesize mismatch, expected %u, got %u\n", block->min_framesize, blockcopy->min_framesize);
-               return false;
-       }
-       if(blockcopy->max_framesize != block->max_framesize) {
-               printf("FAILED, max_framesize mismatch, expected %u, got %u\n", block->max_framesize, blockcopy->max_framesize);
-               return false;
-       }
-       if(blockcopy->sample_rate != block->sample_rate) {
-               printf("FAILED, sample_rate mismatch, expected %u, got %u\n", block->sample_rate, blockcopy->sample_rate);
-               return false;
-       }
-       if(blockcopy->channels != block->channels) {
-               printf("FAILED, channels mismatch, expected %u, got %u\n", block->channels, blockcopy->channels);
-               return false;
-       }
-       if(blockcopy->bits_per_sample != block->bits_per_sample) {
-               printf("FAILED, bits_per_sample mismatch, expected %u, got %u\n", block->bits_per_sample, blockcopy->bits_per_sample);
-               return false;
-       }
-       if(blockcopy->total_samples != block->total_samples) {
-               printf("FAILED, total_samples mismatch, expected %llu, got %llu\n", block->total_samples, blockcopy->total_samples);
-               return false;
-       }
-       if(0 != memcmp(blockcopy->md5sum, block->md5sum, sizeof(block->md5sum))) {
-               printf("FAILED, md5sum mismatch, expected %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X, got %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
-                       (unsigned)block->md5sum[0],
-                       (unsigned)block->md5sum[1],
-                       (unsigned)block->md5sum[2],
-                       (unsigned)block->md5sum[3],
-                       (unsigned)block->md5sum[4],
-                       (unsigned)block->md5sum[5],
-                       (unsigned)block->md5sum[6],
-                       (unsigned)block->md5sum[7],
-                       (unsigned)block->md5sum[8],
-                       (unsigned)block->md5sum[9],
-                       (unsigned)block->md5sum[10],
-                       (unsigned)block->md5sum[11],
-                       (unsigned)block->md5sum[12],
-                       (unsigned)block->md5sum[13],
-                       (unsigned)block->md5sum[14],
-                       (unsigned)block->md5sum[15],
-                       (unsigned)blockcopy->md5sum[0],
-                       (unsigned)blockcopy->md5sum[1],
-                       (unsigned)blockcopy->md5sum[2],
-                       (unsigned)blockcopy->md5sum[3],
-                       (unsigned)blockcopy->md5sum[4],
-                       (unsigned)blockcopy->md5sum[5],
-                       (unsigned)blockcopy->md5sum[6],
-                       (unsigned)blockcopy->md5sum[7],
-                       (unsigned)blockcopy->md5sum[8],
-                       (unsigned)blockcopy->md5sum[9],
-                       (unsigned)blockcopy->md5sum[10],
-                       (unsigned)blockcopy->md5sum[11],
-                       (unsigned)blockcopy->md5sum[12],
-                       (unsigned)blockcopy->md5sum[13],
-                       (unsigned)blockcopy->md5sum[14],
-                       (unsigned)blockcopy->md5sum[15]
-               );
-               return false;
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_padding(const FLAC__StreamMetadata_Padding *block, const FLAC__StreamMetadata_Padding *blockcopy, unsigned block_length)
-{
-       /* we don't compare the padding guts */
-       (void)block, (void)blockcopy, (void)block_length;
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_application(const FLAC__StreamMetadata_Application *block, const FLAC__StreamMetadata_Application *blockcopy, unsigned block_length)
-{
-       if(block_length < sizeof(block->id)) {
-               printf("FAILED, bad block length = %u\n", block_length);
-               return false;
-       }
-       if(0 != memcmp(blockcopy->id, block->id, sizeof(block->id))) {
-               printf("FAILED, id mismatch, expected %02X%02X%02X%02X, got %02X%02X%02X%02X\n",
-                       (unsigned)block->id[0],
-                       (unsigned)block->id[1],
-                       (unsigned)block->id[2],
-                       (unsigned)block->id[3],
-                       (unsigned)blockcopy->id[0],
-                       (unsigned)blockcopy->id[1],
-                       (unsigned)blockcopy->id[2],
-                       (unsigned)blockcopy->id[3]
-               );
-               return false;
-       }
-       if(0 == block->data || 0 == blockcopy->data) {
-               if(block->data != blockcopy->data) {
-                       printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
-                       return false;
-               }
-               else if(block_length - sizeof(block->id) > 0) {
-                       printf("FAILED, data pointer is null but block length is not 0\n");
-                       return false;
-               }
-       }
-       else {
-               if(block_length - sizeof(block->id) == 0) {
-                       printf("FAILED, data pointer is not null but block length is 0\n");
-                       return false;
-               }
-               else if(0 != memcmp(blockcopy->data, block->data, block_length - sizeof(block->id))) {
-                       printf("FAILED, data mismatch\n");
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_seektable(const FLAC__StreamMetadata_SeekTable *block, const FLAC__StreamMetadata_SeekTable *blockcopy)
-{
-       unsigned i;
-       if(blockcopy->num_points != block->num_points) {
-               printf("FAILED, num_points mismatch, expected %u, got %u\n", block->num_points, blockcopy->num_points);
-               return false;
-       }
-       for(i = 0; i < block->num_points; i++) {
-               if(blockcopy->points[i].sample_number != block->points[i].sample_number) {
-                       printf("FAILED, points[%u].sample_number mismatch, expected %llu, got %llu\n", i, block->points[i].sample_number, blockcopy->points[i].sample_number);
-                       return false;
-               }
-               if(blockcopy->points[i].stream_offset != block->points[i].stream_offset) {
-                       printf("FAILED, points[%u].stream_offset mismatch, expected %llu, got %llu\n", i, block->points[i].stream_offset, blockcopy->points[i].stream_offset);
-                       return false;
-               }
-               if(blockcopy->points[i].frame_samples != block->points[i].frame_samples) {
-                       printf("FAILED, points[%u].frame_samples mismatch, expected %u, got %u\n", i, block->points[i].frame_samples, blockcopy->points[i].frame_samples);
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_vorbiscomment(const FLAC__StreamMetadata_VorbisComment *block, const FLAC__StreamMetadata_VorbisComment *blockcopy)
-{
-       unsigned i;
-       if(blockcopy->vendor_string.length != block->vendor_string.length) {
-               printf("FAILED, vendor_string.length mismatch, expected %u, got %u\n", block->vendor_string.length, blockcopy->vendor_string.length);
-               return false;
-       }
-       if(0 == block->vendor_string.entry || 0 == blockcopy->vendor_string.entry) {
-               if(block->vendor_string.entry != blockcopy->vendor_string.entry) {
-                       printf("FAILED, vendor_string.entry mismatch\n");
-                       return false;
-               }
-       }
-       else if(0 != memcmp(blockcopy->vendor_string.entry, block->vendor_string.entry, block->vendor_string.length)) {
-               printf("FAILED, vendor_string.entry mismatch\n");
-               return false;
-       }
-       if(blockcopy->num_comments != block->num_comments) {
-               printf("FAILED, num_comments mismatch, expected %u, got %u\n", block->num_comments, blockcopy->num_comments);
-               return false;
-       }
-       for(i = 0; i < block->num_comments; i++) {
-               if(blockcopy->comments[i].length != block->comments[i].length) {
-                       printf("FAILED, comments[%u].length mismatch, expected %u, got %u\n", i, block->comments[i].length, blockcopy->comments[i].length);
-                       return false;
-               }
-               if(0 == block->comments[i].entry || 0 == blockcopy->comments[i].entry) {
-                       if(block->comments[i].entry != blockcopy->comments[i].entry) {
-                               printf("FAILED, comments[%u].entry mismatch\n", i);
-                               return false;
-                       }
-               }
-               else {
-                       if(0 != memcmp(blockcopy->comments[i].entry, block->comments[i].entry, block->comments[i].length)) {
-                               printf("FAILED, comments[%u].entry mismatch\n", i);
-                               return false;
-                       }
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_cuesheet(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy)
-{
-       unsigned i, j;
-
-       if(0 != strcmp(blockcopy->media_catalog_number, block->media_catalog_number)) {
-               printf("FAILED, media_catalog_number mismatch, expected %s, got %s\n", block->media_catalog_number, blockcopy->media_catalog_number);
-               return false;
-       }
-       if(blockcopy->lead_in != block->lead_in) {
-               printf("FAILED, lead_in mismatch, expected %llu, got %llu\n", block->lead_in, blockcopy->lead_in);
-               return false;
-       }
-       if(blockcopy->is_cd != block->is_cd) {
-               printf("FAILED, is_cd mismatch, expected %u, got %u\n", (unsigned)block->is_cd, (unsigned)blockcopy->is_cd);
-               return false;
-       }
-       if(blockcopy->num_tracks != block->num_tracks) {
-               printf("FAILED, num_tracks mismatch, expected %u, got %u\n", block->num_tracks, blockcopy->num_tracks);
-               return false;
-       }
-       for(i = 0; i < block->num_tracks; i++) {
-               if(blockcopy->tracks[i].offset != block->tracks[i].offset) {
-                       printf("FAILED, tracks[%u].offset mismatch, expected %llu, got %llu\n", i, block->tracks[i].offset, blockcopy->tracks[i].offset);
-                       return false;
-               }
-               if(blockcopy->tracks[i].number != block->tracks[i].number) {
-                       printf("FAILED, tracks[%u].number mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].number, (unsigned)blockcopy->tracks[i].number);
-                       return false;
-               }
-               if(blockcopy->tracks[i].num_indices != block->tracks[i].num_indices) {
-                       printf("FAILED, tracks[%u].num_indices mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].num_indices, (unsigned)blockcopy->tracks[i].num_indices);
-                       return false;
-               }
-               /* num_indices == 0 means lead-out track so only the track offset and number are valid */
-               if(block->tracks[i].num_indices > 0) {
-                       if(0 != strcmp(blockcopy->tracks[i].isrc, block->tracks[i].isrc)) {
-                               printf("FAILED, tracks[%u].isrc mismatch, expected %s, got %s\n", i, block->tracks[i].isrc, blockcopy->tracks[i].isrc);
-                               return false;
-                       }
-                       if(blockcopy->tracks[i].type != block->tracks[i].type) {
-                               printf("FAILED, tracks[%u].type mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].type, (unsigned)blockcopy->tracks[i].type);
-                               return false;
-                       }
-                       if(blockcopy->tracks[i].pre_emphasis != block->tracks[i].pre_emphasis) {
-                               printf("FAILED, tracks[%u].pre_emphasis mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].pre_emphasis, (unsigned)blockcopy->tracks[i].pre_emphasis);
-                               return false;
-                       }
-                       if(0 == block->tracks[i].indices || 0 == blockcopy->tracks[i].indices) {
-                               if(block->tracks[i].indices != blockcopy->tracks[i].indices) {
-                                       printf("FAILED, tracks[%u].indices mismatch\n", i);
-                                       return false;
-                               }
-                       }
-                       else {
-                               for(j = 0; j < block->tracks[i].num_indices; j++) {
-                                       if(blockcopy->tracks[i].indices[j].offset != block->tracks[i].indices[j].offset) {
-                                               printf("FAILED, tracks[%u].indices[%u].offset mismatch, expected %llu, got %llu\n", i, j, block->tracks[i].indices[j].offset, blockcopy->tracks[i].indices[j].offset);
-                                               return false;
-                                       }
-                                       if(blockcopy->tracks[i].indices[j].number != block->tracks[i].indices[j].number) {
-                                               printf("FAILED, tracks[%u].indices[%u].number mismatch, expected %u, got %u\n", i, j, (unsigned)block->tracks[i].indices[j].number, (unsigned)blockcopy->tracks[i].indices[j].number);
-                                               return false;
-                                       }
-                               }
-                       }
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length)
-{
-       if(0 == block->data || 0 == blockcopy->data) {
-               if(block->data != blockcopy->data) {
-                       printf("FAILED, data mismatch (%s's data pointer is null)\n", 0==block->data?"original":"copy");
-                       return false;
-               }
-               else if(block_length > 0) {
-                       printf("FAILED, data pointer is null but block length is not 0\n");
-                       return false;
-               }
-       }
-       else {
-               if(block_length == 0) {
-                       printf("FAILED, data pointer is not null but block length is 0\n");
-                       return false;
-               }
-               else if(0 != memcmp(blockcopy->data, block->data, block_length)) {
-                       printf("FAILED, data mismatch\n");
-                       return false;
-               }
-       }
-       return true;
-}
-
-FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy)
-{
-       if(blockcopy->type != block->type) {
-               printf("FAILED, type mismatch, expected %s, got %s\n", FLAC__MetadataTypeString[block->type], FLAC__MetadataTypeString[blockcopy->type]);
-               return false;
-       }
-       if(blockcopy->is_last != block->is_last) {
-               printf("FAILED, is_last mismatch, expected %u, got %u\n", (unsigned)block->is_last, (unsigned)blockcopy->is_last);
-               return false;
-       }
-       if(blockcopy->length != block->length) {
-               printf("FAILED, length mismatch, expected %u, got %u\n", block->length, blockcopy->length);
-               return false;
-       }
-       switch(block->type) {
-               case FLAC__METADATA_TYPE_STREAMINFO:
-                       return mutils__compare_block_data_streaminfo(&block->data.stream_info, &blockcopy->data.stream_info);
-               case FLAC__METADATA_TYPE_PADDING:
-                       return mutils__compare_block_data_padding(&block->data.padding, &blockcopy->data.padding, block->length);
-               case FLAC__METADATA_TYPE_APPLICATION:
-                       return mutils__compare_block_data_application(&block->data.application, &blockcopy->data.application, block->length);
-               case FLAC__METADATA_TYPE_SEEKTABLE:
-                       return mutils__compare_block_data_seektable(&block->data.seek_table, &blockcopy->data.seek_table);
-               case FLAC__METADATA_TYPE_VORBIS_COMMENT:
-                       return mutils__compare_block_data_vorbiscomment(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
-               case FLAC__METADATA_TYPE_CUESHEET:
-                       return mutils__compare_block_data_cuesheet(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
-               default:
-                       return mutils__compare_block_data_unknown(&block->data.unknown, &blockcopy->data.unknown, block->length);
-       }
-}
-static void *malloc_or_die_(size_t size)
-{
-       void *x = malloc(size);
-       if(0 == x) {
-               fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
-               exit(1);
-       }
-       return x;
-}
-
-static void *calloc_or_die_(size_t n, size_t size)
-{
-       void *x = calloc(n, size);
-       if(0 == x) {
-               fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)n * (unsigned)size);
-               exit(1);
-       }
-       return x;
-}
-
-void mutils__init_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-)
-{
-       /*
-               most of the actual numbers and data in the blocks don't matter,
-               we just want to make sure the decoder parses them correctly
-
-               remember, the metadata interface gets tested after the decoders,
-               so we do all the metadata manipulation here without it.
-       */
-
-       /* min/max_framesize and md5sum don't get written at first, so we have to leave them 0 */
-       streaminfo->is_last = false;
-       streaminfo->type = FLAC__METADATA_TYPE_STREAMINFO;
-       streaminfo->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
-       streaminfo->data.stream_info.min_blocksize = 576;
-       streaminfo->data.stream_info.max_blocksize = 576;
-       streaminfo->data.stream_info.min_framesize = 0;
-       streaminfo->data.stream_info.max_framesize = 0;
-       streaminfo->data.stream_info.sample_rate = 44100;
-       streaminfo->data.stream_info.channels = 1;
-       streaminfo->data.stream_info.bits_per_sample = 8;
-       streaminfo->data.stream_info.total_samples = 0;
-       memset(streaminfo->data.stream_info.md5sum, 0, 16);
-
-       padding->is_last = false;
-       padding->type = FLAC__METADATA_TYPE_PADDING;
-       padding->length = 1234;
-
-       seektable->is_last = false;
-       seektable->type = FLAC__METADATA_TYPE_SEEKTABLE;
-       seektable->data.seek_table.num_points = 2;
-       seektable->length = seektable->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
-       seektable->data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)malloc_or_die_(seektable->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint));
-       seektable->data.seek_table.points[0].sample_number = 0;
-       seektable->data.seek_table.points[0].stream_offset = 0;
-       seektable->data.seek_table.points[0].frame_samples = streaminfo->data.stream_info.min_blocksize;
-       seektable->data.seek_table.points[1].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
-       seektable->data.seek_table.points[1].stream_offset = 1000;
-       seektable->data.seek_table.points[1].frame_samples = streaminfo->data.stream_info.min_blocksize;
-
-       application1->is_last = false;
-       application1->type = FLAC__METADATA_TYPE_APPLICATION;
-       application1->length = 8;
-       memcpy(application1->data.application.id, "\xfe\xdc\xba\x98", 4);
-       application1->data.application.data = (FLAC__byte*)malloc_or_die_(4);
-       memcpy(application1->data.application.data, "\xf0\xe1\xd2\xc3", 4);
-
-       application2->is_last = false;
-       application2->type = FLAC__METADATA_TYPE_APPLICATION;
-       application2->length = 4;
-       memcpy(application2->data.application.id, "\x76\x54\x32\x10", 4);
-       application2->data.application.data = 0;
-
-       {
-               const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
-               vorbiscomment->is_last = false;
-               vorbiscomment->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
-               vorbiscomment->length = (4 + vendor_string_length) + 4 + (4 + 5) + (4 + 0);
-               vorbiscomment->data.vorbis_comment.vendor_string.length = vendor_string_length;
-               vorbiscomment->data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(vendor_string_length+1);
-               memcpy(vorbiscomment->data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
-               vorbiscomment->data.vorbis_comment.num_comments = 2;
-               vorbiscomment->data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc_or_die_(vorbiscomment->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
-               vorbiscomment->data.vorbis_comment.comments[0].length = 5;
-               vorbiscomment->data.vorbis_comment.comments[0].entry = (FLAC__byte*)malloc_or_die_(5+1);
-               memcpy(vorbiscomment->data.vorbis_comment.comments[0].entry, "ab=cd", 5+1);
-               vorbiscomment->data.vorbis_comment.comments[1].length = 0;
-               vorbiscomment->data.vorbis_comment.comments[1].entry = 0;
-       }
-
-       cuesheet->is_last = false;
-       cuesheet->type = FLAC__METADATA_TYPE_CUESHEET;
-       cuesheet->length =
-               /* cuesheet guts */
-               (
-                       FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
-               ) / 8 +
-               /* 2 tracks */
-               3 * (
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
-               ) / 8 +
-               /* 3 index points */
-               3 * (
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
-                       FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
-               ) / 8
-       ;
-       memset(cuesheet->data.cue_sheet.media_catalog_number, 0, sizeof(cuesheet->data.cue_sheet.media_catalog_number));
-       cuesheet->data.cue_sheet.media_catalog_number[0] = 'j';
-       cuesheet->data.cue_sheet.media_catalog_number[1] = 'C';
-       cuesheet->data.cue_sheet.lead_in = 2 * 44100;
-       cuesheet->data.cue_sheet.is_cd = true;
-       cuesheet->data.cue_sheet.num_tracks = 3;
-       cuesheet->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc_or_die_(cuesheet->data.cue_sheet.num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));
-       cuesheet->data.cue_sheet.tracks[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[0].number = 1;
-       memcpy(cuesheet->data.cue_sheet.tracks[0].isrc, "ACBDE1234567", sizeof(cuesheet->data.cue_sheet.tracks[0].isrc));
-       cuesheet->data.cue_sheet.tracks[0].type = 0;
-       cuesheet->data.cue_sheet.tracks[0].pre_emphasis = 1;
-       cuesheet->data.cue_sheet.tracks[0].num_indices = 2;
-       cuesheet->data.cue_sheet.tracks[0].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet->data.cue_sheet.tracks[0].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
-       cuesheet->data.cue_sheet.tracks[0].indices[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[0].indices[0].number = 0;
-       cuesheet->data.cue_sheet.tracks[0].indices[1].offset = 123 * 588;
-       cuesheet->data.cue_sheet.tracks[0].indices[1].number = 1;
-       cuesheet->data.cue_sheet.tracks[1].offset = 1234 * 588;
-       cuesheet->data.cue_sheet.tracks[1].number = 2;
-       memcpy(cuesheet->data.cue_sheet.tracks[1].isrc, "ACBDE7654321", sizeof(cuesheet->data.cue_sheet.tracks[1].isrc));
-       cuesheet->data.cue_sheet.tracks[1].type = 1;
-       cuesheet->data.cue_sheet.tracks[1].pre_emphasis = 0;
-       cuesheet->data.cue_sheet.tracks[1].num_indices = 1;
-       cuesheet->data.cue_sheet.tracks[1].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet->data.cue_sheet.tracks[1].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
-       cuesheet->data.cue_sheet.tracks[1].indices[0].offset = 0;
-       cuesheet->data.cue_sheet.tracks[1].indices[0].number = 1;
-       cuesheet->data.cue_sheet.tracks[2].offset = 12345 * 588;
-       cuesheet->data.cue_sheet.tracks[2].number = 170;
-       cuesheet->data.cue_sheet.tracks[2].num_indices = 0;
-
-       unknown->is_last = true;
-       unknown->type = 127;
-       unknown->length = 8;
-       unknown->data.unknown.data = (FLAC__byte*)malloc_or_die_(unknown->length);
-       memcpy(unknown->data.unknown.data, "\xfe\xdc\xba\x98\xf0\xe1\xd2\xc3", unknown->length);
-}
-
-void mutils__free_metadata_blocks(
-       FLAC__StreamMetadata *streaminfo,
-       FLAC__StreamMetadata *padding,
-       FLAC__StreamMetadata *seektable,
-       FLAC__StreamMetadata *application1,
-       FLAC__StreamMetadata *application2,
-       FLAC__StreamMetadata *vorbiscomment,
-       FLAC__StreamMetadata *cuesheet,
-       FLAC__StreamMetadata *unknown
-)
-{
-       (void)streaminfo, (void)padding, (void)application2;
-       free(seektable->data.seek_table.points);
-       free(application1->data.application.data);
-       free(vorbiscomment->data.vorbis_comment.vendor_string.entry);
-       free(vorbiscomment->data.vorbis_comment.comments[0].entry);
-       free(vorbiscomment->data.vorbis_comment.comments);
-       free(cuesheet->data.cue_sheet.tracks[0].indices);
-       free(cuesheet->data.cue_sheet.tracks[1].indices);
-       free(cuesheet->data.cue_sheet.tracks);
-       free(unknown->data.unknown.data);
-}
index 57ef25b..55f7d7b 100644 (file)
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
-# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\libOggFLAC_static.lib ..\..\obj\release\lib\libFLAC_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\replaygain_analysis_static.lib ..\..\obj\release\lib\test_libs_common_static.lib ..\..\obj\release\lib\libOggFLAC_static.lib ..\..\obj\release\lib\libFLAC_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /machine:I386\r
 \r
 !ELSEIF  "$(CFG)" == "test_libOggFLAC - Win32 Debug"\r
 \r
@@ -76,7 +76,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\libOggFLAC_static.lib ..\..\obj\debug\lib\libFLAC_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 ..\..\obj\debug\lib\grabbag_static.lib ..\..\obj\debug\lib\replaygain_analysis_static.lib ..\..\obj\debug\lib\test_libs_common_static.lib ..\..\obj\debug\lib\libOggFLAC_static.lib ..\..\obj\debug\lib\libFLAC_static.lib ..\..\obj\release\lib\ogg_static.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
 \r
 !ENDIF \r
 \r
@@ -97,16 +97,8 @@ SOURCE=.\encoders.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\file_utils.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=.\main.c\r
 # End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\metadata_utils.c\r
-# End Source File\r
 # End Group\r
 # Begin Group "Header Files"\r
 \r
@@ -119,14 +111,6 @@ SOURCE=.\decoders.h
 \r
 SOURCE=.\encoders.h\r
 # End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\file_utils.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\metadata_utils.h\r
-# End Source File\r
 # End Group\r
 # Begin Source File\r
 \r
diff --git a/src/test_libs_common/Makefile.am b/src/test_libs_common/Makefile.am
new file mode 100644 (file)
index 0000000..5c68a0a
--- /dev/null
@@ -0,0 +1,39 @@
+#  test_libs_common - Common code to library unit tests
+#  Copyright (C) 2000,2001,2002,2003,2004,2005,2006  Josh Coalson
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+if FLaC__HAS_OGG
+OGGFLAC_SOURCES = \
+       file_utils_oggflac.c
+OGGFLAC_LIBS = \
+       ../libOggFLAC/libOggFLAC.la
+endif
+
+INCLUDES = -I$(top_srcdir)/include
+
+noinst_LTLIBRARIES = libtest_libs_common.la
+
+noinst_LIBADD = @OGGFLAC_LIBS@ ../libFLAC/libFLAC.la
+
+libtest_libs_common_la_SOURCES = \
+       file_utils_flac.c \
+       metadata_utils.c \
+       $(OGGFLAC_SOURCES)
+
+EXTRA_DIST = \
+       Makefile.lite \
+       README \
+       test_libs_common_static.dsp
diff --git a/src/test_libs_common/Makefile.lite b/src/test_libs_common/Makefile.lite
new file mode 100644 (file)
index 0000000..7b6074b
--- /dev/null
@@ -0,0 +1,36 @@
+#  test_libs_common - Common code to library unit tests
+#  Copyright (C) 2000,2001,2002,2003,2004,2005,2006  Josh Coalson
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#
+# GNU makefile
+#
+
+topdir = ../..
+libdir = $(topdir)/obj/$(BUILD)/lib
+
+LIB_NAME = libtest_libs_common
+
+INCLUDES = -I$(topdir)/include
+
+SRCS_C = \
+       file_utils_flac.c \
+       file_utils_oggflac.c \
+       metadata_utils.c
+
+include $(topdir)/build/lib.mk
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/src/test_libs_common/README b/src/test_libs_common/README
new file mode 100644 (file)
index 0000000..6a704c2
--- /dev/null
@@ -0,0 +1,2 @@
+This directory contains a convenience library of routines that are
+common to the library unit testers.
similarity index 93%
rename from src/test_libFLAC++/file_utils.c
rename to src/test_libs_common/file_utils_flac.c
index 8baf9ea..6dbf3aa 100644 (file)
@@ -20,9 +20,9 @@
 #  include <config.h>
 #endif
 
-#include "file_utils.h"
 #include "FLAC/assert.h"
 #include "FLAC/stream_encoder.h"
+#include "test_libs_common/file_utils_flac.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h> /* for stat() */
@@ -104,11 +104,8 @@ FLAC__bool file_utils__generate_flacfile(const char *output_filename, off_t *out
        FLAC__stream_encoder_set_rice_parameter_search_dist(encoder, 0);
        FLAC__stream_encoder_set_total_samples_estimate(encoder, streaminfo->data.stream_info.total_samples);
        FLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
-       FLAC__stream_encoder_set_write_callback(encoder, encoder_write_callback_);
-       FLAC__stream_encoder_set_metadata_callback(encoder, encoder_metadata_callback_);
-       FLAC__stream_encoder_set_client_data(encoder, &encoder_client_data);
 
-       if(FLAC__stream_encoder_init(encoder) != FLAC__STREAM_ENCODER_OK) {
+       if(FLAC__stream_encoder_init_stream(encoder, encoder_write_callback_, /*seek_callback=*/0, /*tell_callback=*/0, encoder_metadata_callback_, &encoder_client_data) != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
                fclose(encoder_client_data.file);
                return false;
        }
similarity index 88%
rename from src/test_libOggFLAC++/file_utils.c
rename to src/test_libs_common/file_utils_oggflac.c
index d397b5b..09cb34c 100644 (file)
@@ -20,9 +20,9 @@
 #  include <config.h>
 #endif
 
-#include "file_utils.h"
 #include "FLAC/assert.h"
 #include "OggFLAC/stream_encoder.h"
+#include "test_libs_common/file_utils_oggflac.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h> /* for stat() */
@@ -50,7 +50,7 @@ typedef struct {
        FILE *file;
 } encoder_client_struct;
 
-static FLAC__StreamEncoderWriteStatus encoder_write_callback_(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
+static FLAC__StreamEncoderWriteStatus encoder_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
 {
        encoder_client_struct *ecd = (encoder_client_struct*)client_data;
 
@@ -62,7 +62,7 @@ static FLAC__StreamEncoderWriteStatus encoder_write_callback_(const OggFLAC__Str
                return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
 }
 
-static void encoder_metadata_callback_(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
+static void encoder_metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        (void)encoder, (void)metadata, (void)client_data;
 }
@@ -107,11 +107,8 @@ FLAC__bool file_utils__generate_oggflacfile(const char *output_filename, off_t *
        OggFLAC__stream_encoder_set_rice_parameter_search_dist(encoder, 0);
        OggFLAC__stream_encoder_set_total_samples_estimate(encoder, streaminfo->data.stream_info.total_samples);
        OggFLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
-       OggFLAC__stream_encoder_set_write_callback(encoder, encoder_write_callback_);
-       OggFLAC__stream_encoder_set_metadata_callback(encoder, encoder_metadata_callback_);
-       OggFLAC__stream_encoder_set_client_data(encoder, &encoder_client_data);
 
-       if(OggFLAC__stream_encoder_init(encoder) != OggFLAC__STREAM_ENCODER_OK) {
+       if(OggFLAC__stream_encoder_init_stream(encoder, /*read_callback=*/0, encoder_write_callback_, /*seek_callback=*/0, /*tell_callback=*/0, encoder_metadata_callback_, &encoder_client_data) != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
                fclose(encoder_client_data.file);
                return false;
        }
similarity index 99%
rename from src/test_libOggFLAC++/metadata_utils.c
rename to src/test_libs_common/metadata_utils.c
index c866982..7ae70b8 100644 (file)
@@ -24,8 +24,8 @@
 #  include <config.h>
 #endif
 
-#include "metadata_utils.h"
 #include "FLAC/metadata.h"
+#include "test_libs_common/metadata_utils.h"
 #include <stdio.h>
 #include <stdlib.h> /* for malloc() */
 #include <string.h> /* for memcmp() */
diff --git a/src/test_libs_common/test_libs_common_static.dsp b/src/test_libs_common/test_libs_common_static.dsp
new file mode 100644 (file)
index 0000000..dd33c18
--- /dev/null
@@ -0,0 +1,116 @@
+# Microsoft Developer Studio Project File - Name="test_libs_common_static" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Static Library" 0x0104\r
+\r
+CFG=test_libs_common_static - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "test_libs_common_static.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "test_libs_common_static.mak" CFG="test_libs_common_static - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "test_libs_common_static - Win32 Release" (based on "Win32 (x86) Static Library")\r
+!MESSAGE "test_libs_common_static - Win32 Debug" (based on "Win32 (x86) Static Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName "test_libs_common"\r
+# PROP Scc_LocalPath "..\.."\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "test_libs_common_static - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "..\..\obj\release\lib"\r
+# PROP Intermediate_Dir "Release_static"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
+# ADD CPP /nologo /MD /W3 /GX /O2 /Op /I ".\include" /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo /nodefaultlib\r
+\r
+!ELSEIF  "$(CFG)" == "test_libs_common_static - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "..\..\obj\debug\lib"\r
+# PROP Intermediate_Dir "Debug_static"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".\include" /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo /nodefaultlib\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "test_libs_common_static - Win32 Release"\r
+# Name "test_libs_common_static - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "c"\r
+# Begin Source File\r
+\r
+SOURCE=.\file_utils_flac.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\file_utils_oggflac.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\metadata_utils.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Public Header Files"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\include\test_libs_common\file_utils_flac.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\include\test_libs_common\file_utils_oggflac.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\include\test_libs_common\metadata_utils.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
index 8f56731..98eed25 100644 (file)
@@ -31,9 +31,9 @@
 #endif
 #include <sys/stat.h> /* for stat() */
 #include "FLAC/assert.h"
-#include "FLAC/file_decoder.h"
+#include "FLAC/stream_decoder.h"
 #ifdef FLAC__HAS_OGG
-#include "OggFLAC/file_decoder.h"
+#include "OggFLAC/stream_decoder.h"
 #endif
 
 typedef struct {
@@ -43,7 +43,7 @@ typedef struct {
        unsigned bits_per_sample;
        FLAC__bool ignore_errors;
        FLAC__bool error_occurred;
-} decoder_client_data_struct;
+} DecoderClientData;
 
 static FLAC__bool stop_signal_ = false;
 
@@ -61,50 +61,34 @@ static FLAC__bool die_(const char *msg)
        return false;
 }
 
-static FLAC__bool die_f_(const char *msg, const FLAC__FileDecoder *decoder)
+static FLAC__bool die_s_(const char *msg, const FLAC__StreamDecoder *decoder)
 {
-       FLAC__FileDecoderState state = FLAC__file_decoder_get_state(decoder);
+       FLAC__StreamDecoderState state = FLAC__stream_decoder_get_state(decoder);
 
        if(msg)
                printf("FAILED, %s", msg);
        else
                printf("FAILED");
 
-       printf(", state = %u (%s)\n", (unsigned)state, FLAC__FileDecoderStateString[state]);
-       if(state == FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) {
-               FLAC__SeekableStreamDecoderState state_ = FLAC__file_decoder_get_seekable_stream_decoder_state(decoder);
-               printf("      seekable stream decoder state = %u (%s)\n", (unsigned)state, FLAC__SeekableStreamDecoderStateString[state_]);
-               if(state_ == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
-                       FLAC__StreamDecoderState state__ = FLAC__file_decoder_get_stream_decoder_state(decoder);
-                       printf("      stream decoder state = %u (%s)\n", (unsigned)state__, FLAC__StreamDecoderStateString[state__]);
-               }
-       }
+       printf(", state = %u (%s)\n", (unsigned)state, FLAC__StreamDecoderStateString[state]);
 
        return false;
 }
 
 #ifdef FLAC__HAS_OGG
-static FLAC__bool die_of_(const char *msg, const OggFLAC__FileDecoder *decoder)
+static FLAC__bool die_os_(const char *msg, const OggFLAC__StreamDecoder *decoder)
 {
-       OggFLAC__FileDecoderState state = OggFLAC__file_decoder_get_state(decoder);
+       OggFLAC__StreamDecoderState state = OggFLAC__stream_decoder_get_state(decoder);
 
        if(msg)
                printf("FAILED, %s", msg);
        else
                printf("FAILED");
 
-       printf(", state = %u (%s)\n", (unsigned)state, OggFLAC__SeekableStreamDecoderStateString[state]);
-       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_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___]);
-                       }
-               }
+       printf(", state = %u (%s)\n", (unsigned)state, OggFLAC__StreamDecoderStateString[state]);
+       if(state == OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) {
+               FLAC__StreamDecoderState state_ = OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder);
+               printf("      FLAC stream decoder state = %u (%s)\n", (unsigned)state_, FLAC__StreamDecoderStateString[state_]);
        }
 
        return false;
@@ -121,9 +105,9 @@ static off_t get_filesize_(const char *srcpath)
                return -1;
 }
 
-static FLAC__StreamDecoderWriteStatus file_decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
-       decoder_client_data_struct *dcd = (decoder_client_data_struct*)client_data;
+       DecoderClientData *dcd = (DecoderClientData*)client_data;
 
        (void)decoder, (void)buffer;
 
@@ -149,9 +133,9 @@ static FLAC__StreamDecoderWriteStatus file_decoder_write_callback_(const FLAC__F
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
 
-static void file_decoder_metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
-       decoder_client_data_struct *dcd = (decoder_client_data_struct*)client_data;
+       DecoderClientData *dcd = (DecoderClientData*)client_data;
 
        (void)decoder;
 
@@ -171,9 +155,9 @@ static void file_decoder_metadata_callback_(const FLAC__FileDecoder *decoder, co
        }
 }
 
-static void file_decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 {
-       decoder_client_data_struct *dcd = (decoder_client_data_struct*)client_data;
+       DecoderClientData *dcd = (DecoderClientData*)client_data;
 
        (void)decoder;
 
@@ -190,8 +174,8 @@ static void file_decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC_
 
 static FLAC__bool seek_barrage_native_flac(const char *filename, off_t filesize, unsigned count)
 {
-       FLAC__FileDecoder *decoder;
-       decoder_client_data_struct decoder_client_data;
+       FLAC__StreamDecoder *decoder;
+       DecoderClientData decoder_client_data;
        unsigned i;
        long int n;
 
@@ -200,32 +184,17 @@ static FLAC__bool seek_barrage_native_flac(const char *filename, off_t filesize,
        decoder_client_data.ignore_errors = false;
        decoder_client_data.error_occurred = false;
 
-       printf("\n+++ seek test: FLAC__FileDecoder\n\n");
+       printf("\n+++ seek test: FLAC__StreamDecoder\n\n");
 
-       decoder = FLAC__file_decoder_new();
+       decoder = FLAC__stream_decoder_new();
        if(0 == decoder)
-               return die_("FLAC__file_decoder_new() FAILED, returned NULL\n");
-
-       if(!FLAC__file_decoder_set_write_callback(decoder, file_decoder_write_callback_))
-               return die_f_("FLAC__file_decoder_set_write_callback() FAILED", decoder);
-
-       if(!FLAC__file_decoder_set_metadata_callback(decoder, file_decoder_metadata_callback_))
-               return die_f_("FLAC__file_decoder_set_metadata_callback() FAILED", decoder);
-
-       if(!FLAC__file_decoder_set_error_callback(decoder, file_decoder_error_callback_))
-               return die_f_("FLAC__file_decoder_set_error_callback() FAILED", decoder);
-
-       if(!FLAC__file_decoder_set_client_data(decoder, &decoder_client_data))
-               return die_f_("FLAC__file_decoder_set_client_data() FAILED", decoder);
+               return die_("FLAC__stream_decoder_new() FAILED, returned NULL\n");
 
-       if(!FLAC__file_decoder_set_filename(decoder, filename))
-               return die_f_("FLAC__file_decoder_set_filename() FAILED", decoder);
+       if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+               return die_s_("FLAC__stream_decoder_init_file() FAILED", decoder);
 
-       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
-               return die_f_("FLAC__file_decoder_init() FAILED", decoder);
-
-       if(!FLAC__file_decoder_process_until_end_of_metadata(decoder))
-               return die_f_("FLAC__file_decoder_process_until_end_of_metadata() FAILED", decoder);
+       if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder))
+               return die_s_("FLAC__stream_decoder_process_until_end_of_metadata() FAILED", decoder);
 
        printf("file's total_samples is %llu\n", decoder_client_data.total_samples);
 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
@@ -237,7 +206,6 @@ static FLAC__bool seek_barrage_native_flac(const char *filename, off_t filesize,
        n = (long int)decoder_client_data.total_samples;
 
        /* if we don't have a total samples count, just guess based on the file size */
-       /* @@@ should get it from last page's granulepos */
        if(n == 0) {
                /* 8 would imply no compression, 9 guarantees that we will get some samples off the end of the stream to test that case */
                n = 9 * filesize / (decoder_client_data.channels * decoder_client_data.bits_per_sample);
@@ -275,9 +243,9 @@ static FLAC__bool seek_barrage_native_flac(const char *filename, off_t filesize,
 
                printf("seek(%llu)... ", pos);
                fflush(stdout);
-               if(!FLAC__file_decoder_seek_absolute(decoder, pos)) {
+               if(!FLAC__stream_decoder_seek_absolute(decoder, pos)) {
                        if(pos < (FLAC__uint64)n && decoder_client_data.total_samples != 0)
-                               return die_f_("FLAC__file_decoder_seek_absolute() FAILED", decoder);
+                               return die_s_("FLAC__stream_decoder_seek_absolute() FAILED", decoder);
                        else if(decoder_client_data.total_samples == 0)
                                printf("seek failed, assuming it was past EOF... ");
                        else
@@ -285,49 +253,35 @@ static FLAC__bool seek_barrage_native_flac(const char *filename, off_t filesize,
 
                        /* hack to work around a deficiency in the seek API's behavior */
                        /* seeking past EOF sets the file decoder state to non-OK and there's no ..._flush() or ..._reset() call to reset it */
-                       if(!FLAC__file_decoder_finish(decoder))
-                               return die_f_("FLAC__file_decoder_finish() FAILED", decoder);
-
-                       if(!FLAC__file_decoder_set_write_callback(decoder, file_decoder_write_callback_))
-                               return die_f_("FLAC__file_decoder_set_write_callback() FAILED", decoder);
-
-                       if(!FLAC__file_decoder_set_metadata_callback(decoder, file_decoder_metadata_callback_))
-                               return die_f_("FLAC__file_decoder_set_metadata_callback() FAILED", decoder);
-
-                       if(!FLAC__file_decoder_set_error_callback(decoder, file_decoder_error_callback_))
-                               return die_f_("FLAC__file_decoder_set_error_callback() FAILED", decoder);
-
-                       if(!FLAC__file_decoder_set_client_data(decoder, &decoder_client_data))
-                               return die_f_("FLAC__file_decoder_set_client_data() FAILED", decoder);
+                       /* @@@@@@ probably no longer true and we can remove this hack */
+                       if(!FLAC__stream_decoder_finish(decoder))
+                               return die_s_("FLAC__stream_decoder_finish() FAILED", decoder);
 
-                       if(!FLAC__file_decoder_set_filename(decoder, filename))
-                               return die_f_("FLAC__file_decoder_set_filename() FAILED", decoder);
+                       if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_s_("FLAC__stream_decoder_init_file() FAILED", decoder);
 
-                       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
-                               return die_f_("FLAC__file_decoder_init() FAILED", decoder);
-
-                       if(!FLAC__file_decoder_process_until_end_of_metadata(decoder))
-                               return die_f_("FLAC__file_decoder_process_until_end_of_metadata() FAILED", decoder);
+                       if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder))
+                               return die_s_("FLAC__stream_decoder_process_until_end_of_metadata() FAILED", decoder);
                }
                else {
                        printf("decode_frame... ");
                        fflush(stdout);
-                       if(!FLAC__file_decoder_process_single(decoder))
-                               return die_f_("FLAC__file_decoder_process_single() FAILED", decoder);
+                       if(!FLAC__stream_decoder_process_single(decoder))
+                               return die_s_("FLAC__stream_decoder_process_single() FAILED", decoder);
 
                        printf("decode_frame... ");
                        fflush(stdout);
-                       if(!FLAC__file_decoder_process_single(decoder))
-                               return die_f_("FLAC__file_decoder_process_single() FAILED", decoder);
+                       if(!FLAC__stream_decoder_process_single(decoder))
+                               return die_s_("FLAC__stream_decoder_process_single() FAILED", decoder);
                }
 
                printf("OK\n");
                fflush(stdout);
        }
 
-       if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_UNINITIALIZED) {
-               if(!FLAC__file_decoder_finish(decoder))
-                       return die_f_("FLAC__file_decoder_finish() FAILED", decoder);
+       if(FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_UNINITIALIZED) {
+               if(!FLAC__stream_decoder_finish(decoder))
+                       return die_s_("FLAC__stream_decoder_finish() FAILED", decoder);
        }
 
        printf("\nPASSED!\n");
@@ -338,8 +292,8 @@ static FLAC__bool seek_barrage_native_flac(const char *filename, off_t filesize,
 #ifdef FLAC__HAS_OGG
 static FLAC__bool seek_barrage_ogg_flac(const char *filename, off_t filesize, unsigned count)
 {
-       OggFLAC__FileDecoder *decoder;
-       decoder_client_data_struct decoder_client_data;
+       OggFLAC__StreamDecoder *decoder;
+       DecoderClientData decoder_client_data;
        unsigned i;
        long int n;
 
@@ -348,32 +302,17 @@ static FLAC__bool seek_barrage_ogg_flac(const char *filename, off_t filesize, un
        decoder_client_data.ignore_errors = false;
        decoder_client_data.error_occurred = false;
 
-       printf("\n+++ seek test: OggFLAC__FileDecoder\n\n");
+       printf("\n+++ seek test: OggFLAC__StreamDecoder\n\n");
 
-       decoder = OggFLAC__file_decoder_new();
+       decoder = OggFLAC__stream_decoder_new();
        if(0 == decoder)
-               return die_("OggFLAC__file_decoder_new() FAILED, returned NULL\n");
-
-       if(!OggFLAC__file_decoder_set_write_callback(decoder, (OggFLAC__FileDecoderWriteCallback)file_decoder_write_callback_))
-               return die_of_("OggFLAC__file_decoder_set_write_callback() FAILED", decoder);
-
-       if(!OggFLAC__file_decoder_set_metadata_callback(decoder, (OggFLAC__FileDecoderMetadataCallback)file_decoder_metadata_callback_))
-               return die_of_("OggFLAC__file_decoder_set_metadata_callback() FAILED", decoder);
-
-       if(!OggFLAC__file_decoder_set_error_callback(decoder, (OggFLAC__FileDecoderErrorCallback)file_decoder_error_callback_))
-               return die_of_("OggFLAC__file_decoder_set_error_callback() FAILED", decoder);
-
-       if(!OggFLAC__file_decoder_set_client_data(decoder, &decoder_client_data))
-               return die_of_("OggFLAC__file_decoder_set_client_data() FAILED", decoder);
-
-       if(!OggFLAC__file_decoder_set_filename(decoder, filename))
-               return die_of_("OggFLAC__file_decoder_set_filename() FAILED", decoder);
+               return die_("OggFLAC__stream_decoder_new() FAILED, returned NULL\n");
 
-       if(OggFLAC__file_decoder_init(decoder) != OggFLAC__FILE_DECODER_OK)
-               return die_of_("OggFLAC__file_decoder_init() FAILED", decoder);
+       if(OggFLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+               return die_os_("OggFLAC__stream_decoder_init_file() FAILED", decoder);
 
-       if(!OggFLAC__file_decoder_process_until_end_of_metadata(decoder))
-               return die_of_("OggFLAC__file_decoder_process_until_end_of_metadata() FAILED", decoder);
+       if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder))
+               return die_os_("OggFLAC__stream_decoder_process_until_end_of_metadata() FAILED", decoder);
 
        printf("file's total_samples is %llu\n", decoder_client_data.total_samples);
 #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
@@ -385,6 +324,7 @@ static FLAC__bool seek_barrage_ogg_flac(const char *filename, off_t filesize, un
        n = (long int)decoder_client_data.total_samples;
 
        /* if we don't have a total samples count, just guess based on the file size */
+       /* @@@ should get it from last page's granulepos */
        if(n == 0) {
                /* 8 would imply no compression, 9 guarantees that we will get some samples off the end of the stream to test that case */
                n = 9 * filesize / (decoder_client_data.channels * decoder_client_data.bits_per_sample);
@@ -422,9 +362,9 @@ static FLAC__bool seek_barrage_ogg_flac(const char *filename, off_t filesize, un
 
                printf("seek(%llu)... ", pos);
                fflush(stdout);
-               if(!OggFLAC__file_decoder_seek_absolute(decoder, pos)) {
+               if(!OggFLAC__stream_decoder_seek_absolute(decoder, pos)) {
                        if(pos < (FLAC__uint64)n && decoder_client_data.total_samples != 0)
-                               return die_of_("OggFLAC__file_decoder_seek_absolute() FAILED", decoder);
+                               return die_os_("OggFLAC__stream_decoder_seek_absolute() FAILED", decoder);
                        else if(decoder_client_data.total_samples == 0)
                                printf("seek failed, assuming it was past EOF... ");
                        else
@@ -432,49 +372,35 @@ static FLAC__bool seek_barrage_ogg_flac(const char *filename, off_t filesize, un
 
                        /* hack to work around a deficiency in the seek API's behavior */
                        /* seeking past EOF sets the file decoder state to non-OK and there's no ..._flush() or ..._reset() call to reset it */
-                       if(!OggFLAC__file_decoder_finish(decoder))
-                               return die_of_("OggFLAC__file_decoder_finish() FAILED", decoder);
-
-                       if(!OggFLAC__file_decoder_set_write_callback(decoder, (OggFLAC__FileDecoderWriteCallback)file_decoder_write_callback_))
-                               return die_of_("OggFLAC__file_decoder_set_write_callback() FAILED", decoder);
-
-                       if(!OggFLAC__file_decoder_set_metadata_callback(decoder, (OggFLAC__FileDecoderMetadataCallback)file_decoder_metadata_callback_))
-                               return die_of_("OggFLAC__file_decoder_set_metadata_callback() FAILED", decoder);
-
-                       if(!OggFLAC__file_decoder_set_error_callback(decoder, (OggFLAC__FileDecoderErrorCallback)file_decoder_error_callback_))
-                               return die_of_("OggFLAC__file_decoder_set_error_callback() FAILED", decoder);
-
-                       if(!OggFLAC__file_decoder_set_client_data(decoder, &decoder_client_data))
-                               return die_of_("OggFLAC__file_decoder_set_client_data() FAILED", decoder);
-
-                       if(!OggFLAC__file_decoder_set_filename(decoder, filename))
-                               return die_of_("OggFLAC__file_decoder_set_filename() FAILED", decoder);
+                       /* @@@@@@ probably no longer true and we can remove this hack */
+                       if(!OggFLAC__stream_decoder_finish(decoder))
+                               return die_os_("OggFLAC__stream_decoder_finish() FAILED", decoder);
 
-                       if(OggFLAC__file_decoder_init(decoder) != OggFLAC__FILE_DECODER_OK)
-                               return die_of_("OggFLAC__file_decoder_init() FAILED", decoder);
+                       if(OggFLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &decoder_client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+                               return die_os_("OggFLAC__stream_decoder_init_file() FAILED", decoder);
 
-                       if(!OggFLAC__file_decoder_process_until_end_of_metadata(decoder))
-                               return die_of_("OggFLAC__file_decoder_process_until_end_of_metadata() FAILED", decoder);
+                       if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder))
+                               return die_os_("OggFLAC__stream_decoder_process_until_end_of_metadata() FAILED", decoder);
                }
                else {
                        printf("decode_frame... ");
                        fflush(stdout);
-                       if(!OggFLAC__file_decoder_process_single(decoder))
-                               return die_of_("OggFLAC__file_decoder_process_single() FAILED", decoder);
+                       if(!OggFLAC__stream_decoder_process_single(decoder))
+                               return die_os_("OggFLAC__stream_decoder_process_single() FAILED", decoder);
 
                        printf("decode_frame... ");
                        fflush(stdout);
-                       if(!OggFLAC__file_decoder_process_single(decoder))
-                               return die_of_("OggFLAC__file_decoder_process_single() FAILED", decoder);
+                       if(!OggFLAC__stream_decoder_process_single(decoder))
+                               return die_os_("OggFLAC__stream_decoder_process_single() FAILED", decoder);
                }
 
                printf("OK\n");
                fflush(stdout);
        }
 
-       if(OggFLAC__file_decoder_get_state(decoder) != OggFLAC__FILE_DECODER_UNINITIALIZED) {
-               if(!OggFLAC__file_decoder_finish(decoder))
-                       return die_of_("OggFLAC__file_decoder_finish() FAILED", decoder);
+       if(OggFLAC__stream_decoder_get_state(decoder) != OggFLAC__STREAM_DECODER_UNINITIALIZED) {
+               if(!OggFLAC__stream_decoder_finish(decoder))
+                       return die_os_("OggFLAC__stream_decoder_finish() FAILED", decoder);
        }
 
        printf("\nPASSED!\n");
index 3dad27c..dd725f4 100644 (file)
@@ -61,4 +61,7 @@ EXTRA_DIST = \
        bad.234.FLAC_leadout_illegal_offset.cue \
        bad.235.FLAC_leadout_offset_not_211680000.cue \
        good.000.cue \
-       good.001.cue
+       good.001.cue \
+       good.002.dos_format.cue \
+       good.003.missing_final_newline.cue \
+       good.004.dos_format.missing_final_newline.cue
index c16ef5c..8c5dc80 100644 (file)
@@ -19,19 +19,20 @@ EXTRA_DIST = \
        case00a-expect.meta \
        case01a-expect.meta \
        case01b-expect.meta \
+       case01c-expect.meta \
+       case01d-expect.meta \
+       case01e-expect.meta \
        case02a-expect.meta \
        case02b-expect.meta \
+       case02c-expect.meta \
        case03a-expect.meta \
        case03b-expect.meta \
        case03c-expect.meta \
        case04a-expect.meta \
        case04b-expect.meta \
        case04c-expect.meta \
-       case05a-expect.meta \
-       case05b-expect.meta \
-       case05c-expect.meta \
-       case05d-expect.meta \
-       case05e-expect.meta \
+       case04d-expect.meta \
+       case04e-expect.meta \
        input-SCPAP.flac \
        input-SCVA.flac \
        input-SCVAUP.flac \
index 7cd23b6..378907d 100644 (file)
@@ -10,8 +10,9 @@ METADATA block #0
 METADATA block #1
   type: 3 (SEEKTABLE)
   is last: false
-  length: 0
-  seek points: 0
+  length: 18
+  seek points: 1
+    point 0: sample_number=0
 METADATA block #2
   type: 4 (VORBIS_COMMENT)
   is last: false
index 29fcdb1..25f859e 100644 (file)
@@ -10,8 +10,9 @@ METADATA block #0
 METADATA block #1
   type: 3 (SEEKTABLE)
   is last: false
-  length: 0
-  seek points: 0
+  length: 18
+  seek points: 1
+    point 0: sample_number=0
 METADATA block #2
   type: 4 (VORBIS_COMMENT)
   is last: false
index 2e95303..9ca4257 100644 (file)
@@ -1,4 +1,4 @@
-reference libFLAC 1.1.3 20060805
+reference libFLAC 1.1.3 20060831
 ARTIST=The_artist_formerly_known_as_the_artist...
 ARTIST=Chuck_Woolery
 ARTIST=Vern
index 29c5ece..2bef468 100755 (executable)
@@ -85,39 +85,44 @@ if [ ! -f noise.raw ] ; then
 fi
 
 echo "generating FLAC files for seeking:"
-run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=8 --channels=1 --blocksize=576 --output-name=tiny.flac noise8m32.raw || die "ERROR generating FLAC file"
-run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=16 --channels=2 --blocksize=576 --output-name=small.flac noise.raw || die "ERROR generating FLAC file"
-
-echo "testing tiny.flac:"
-if run_test_seeking tiny.flac 100 ; then : ; else
-       die "ERROR: during test_seeking"
-fi
+run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=8 --channels=1 --blocksize=576 -S- --output-name=tiny.flac noise8m32.raw || die "ERROR generating FLAC file"
+run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=16 --channels=2 --blocksize=576 -S- --output-name=small.flac noise.raw || die "ERROR generating FLAC file"
+run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=8 --channels=1 --blocksize=576 -S10x --output-name=tiny-s.flac noise8m32.raw || die "ERROR generating FLAC file"
+run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=16 --channels=2 --blocksize=576 -S10x --output-name=small-s.flac noise.raw || die "ERROR generating FLAC file"
+
+for suffix in '' '-s' ; do
+       echo "testing tiny$suffix.flac:"
+       if run_test_seeking tiny$suffix.flac 100 ; then : ; else
+               die "ERROR: during test_seeking"
+       fi
 
-echo "testing small.flac:"
-if run_test_seeking small.flac 1000 ; then : ; else
-       die "ERROR: during test_seeking"
-fi
+       echo "testing small$suffix.flac:"
+       if run_test_seeking small$suffix.flac 1000 ; then : ; else
+               die "ERROR: during test_seeking"
+       fi
 
-echo "removing sample count from tiny.flac and small.flac:"
-if run_metaflac --no-filename --set-total-samples=0 tiny.flac small.flac ; then : ; else
-       die "ERROR: during metaflac"
-fi
+       echo "removing sample count from tiny$suffix.flac and small$suffix.flac:"
+       if run_metaflac --no-filename --set-total-samples=0 tiny$suffix.flac small$suffix.flac ; then : ; else
+               die "ERROR: during metaflac"
+       fi
 
-echo "testing tiny.flac with total_samples=0:"
-if run_test_seeking tiny.flac 100 ; then : ; else
-       die "ERROR: during test_seeking"
-fi
+       echo "testing tiny$suffix.flac with total_samples=0:"
+       if run_test_seeking tiny$suffix.flac 100 ; then : ; else
+               die "ERROR: during test_seeking"
+       fi
 
-echo "testing small.flac with total_samples=0:"
-if run_test_seeking small.flac 1000 ; then : ; else
-       die "ERROR: during test_seeking"
-fi
+       echo "testing small$suffix.flac with total_samples=0:"
+       if run_test_seeking small$suffix.flac 1000 ; then : ; else
+               die "ERROR: during test_seeking"
+       fi
+done
 
 if [ $has_ogg = "yes" ] ; then
 
        echo "generating Ogg FLAC files for seeking:"
        run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=8 --channels=1 --blocksize=576 --output-name=tiny.ogg --ogg noise8m32.raw || die "ERROR generating Ogg FLAC file"
        run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=16 --channels=2 --blocksize=576 --output-name=small.ogg --ogg noise.raw || die "ERROR generating Ogg FLAC file"
+       # seek tables are not used in libOggFLAC
 
        echo "testing tiny.ogg:"
        if run_test_seeking tiny.ogg 100 ; then : ; else
@@ -131,4 +136,4 @@ if [ $has_ogg = "yes" ] ; then
 
 fi
 
-rm -f tiny.flac tiny.ogg small.flac small.ogg
+rm -f tiny.flac tiny.ogg small.flac small.ogg tiny-s.flac small-s.flac