From 3c2bdf8746c35804b401931d40d370ada158fa40 Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Fri, 26 Sep 2003 01:56:01 +0000 Subject: [PATCH] add ogg seekable stream and file encoder and decoder interfaces --- include/OggFLAC++/decoder.h | 193 ++- include/OggFLAC++/encoder.h | 206 ++- include/OggFLAC/Makefile.am | 4 + include/OggFLAC/all.h | 4 + include/OggFLAC/file_encoder.h | 878 +++++++++++++ include/OggFLAC/seekable_stream_encoder.h | 853 ++++++++++++ src/libOggFLAC++/Makefile.am | 4 + src/libOggFLAC++/Makefile.lite | 4 + src/libOggFLAC++/file_decoder.cpp | 237 ++++ src/libOggFLAC++/file_encoder.cpp | 354 +++++ src/libOggFLAC++/libOggFLAC++_dynamic.dsp | 16 + src/libOggFLAC++/libOggFLAC++_static.dsp | 16 + src/libOggFLAC++/seekable_stream_decoder.cpp | 287 ++++ src/libOggFLAC++/seekable_stream_encoder.cpp | 357 +++++ src/libOggFLAC/Makefile.am | 6 + src/libOggFLAC/Makefile.lite | 6 + src/libOggFLAC/file_encoder.c | 783 +++++++++++ src/libOggFLAC/include/protected/Makefile.am | 2 + src/libOggFLAC/include/protected/all.h | 2 + src/libOggFLAC/include/protected/file_encoder.h | 41 + .../include/protected/seekable_stream_encoder.h | 43 + src/libOggFLAC/libOggFLAC_dynamic.dsp | 68 + src/libOggFLAC/libOggFLAC_static.dsp | 68 + src/libOggFLAC/seekable_stream_encoder.c | 732 +++++++++++ src/test_libOggFLAC++/decoders.cpp | 1386 ++++++++++++++++++++ src/test_libOggFLAC++/encoders.cpp | 719 +++++++++- src/test_libOggFLAC/decoders.c | 1339 ++++++++++++++++++- src/test_libOggFLAC/encoders.c | 725 +++++++++- 28 files changed, 9316 insertions(+), 17 deletions(-) create mode 100644 include/OggFLAC/file_encoder.h create mode 100644 include/OggFLAC/seekable_stream_encoder.h create mode 100644 src/libOggFLAC++/file_decoder.cpp create mode 100644 src/libOggFLAC++/file_encoder.cpp create mode 100644 src/libOggFLAC++/seekable_stream_decoder.cpp create mode 100644 src/libOggFLAC++/seekable_stream_encoder.cpp create mode 100644 src/libOggFLAC/file_encoder.c create mode 100644 src/libOggFLAC/include/protected/file_encoder.h create mode 100644 src/libOggFLAC/include/protected/seekable_stream_encoder.h create mode 100644 src/libOggFLAC/seekable_stream_encoder.c diff --git a/include/OggFLAC++/decoder.h b/include/OggFLAC++/decoder.h index f463fa6..31510ad 100644 --- a/include/OggFLAC++/decoder.h +++ b/include/OggFLAC++/decoder.h @@ -34,6 +34,8 @@ #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" @@ -53,11 +55,11 @@ * \ingroup oggflacpp * * \brief - * This module describes the decoder layers provided by libOggFLAC++. + * This module describes the three decoder layers provided by libOggFLAC++. * * The libOggFLAC++ decoder classes are object wrappers around their - * counterparts in libOggFLAC. Only the stream decoding layer in - * libOggFLAC provided here. The interface is very similar; + * counterparts in libOggFLAC. All three 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 @@ -122,6 +124,10 @@ namespace OggFLAC { unsigned get_sample_rate() const; unsigned get_blocksize() const; + /** Initialize the instance; as with the C interface, + * init() should be called after construction and 'set' + * calls but before any of the 'process' calls. + */ State init(); void finish(); @@ -152,6 +158,187 @@ namespace OggFLAC { /* \} */ + // ============================================================ + // + // Equivalent: OggFLAC__SeekableStreamDecoder + // + // ============================================================ + + /** \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. + * + * \{ + */ + + /** 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_; + }; + + SeekableStream(); + virtual ~SeekableStream(); + + 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_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::SeekableStream::State get_FLAC_seekable_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 ::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; + + ::OggFLAC__SeekableStreamDecoder *decoder_; + private: + static ::FLAC__SeekableStreamDecoderReadStatus read_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); + static ::FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); + static ::FLAC__SeekableStreamDecoderTellStatus tell_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); + static ::FLAC__SeekableStreamDecoderLengthStatus length_callback_(const ::OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); + static 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 and undefined so you can't use them: + SeekableStream(const SeekableStream &); + void operator=(const SeekableStream &); + }; + + /* \} */ + + // ============================================================ + // + // 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. + * + * \{ + */ + + /** This class wraps the ::OggFLAC__FileDecoder. + */ + class OggFLACPP_API File { + 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; + FLAC::Decoder::File::State get_FLAC_file_decoder_state() const; + FLAC::Decoder::SeekableStream::State get_FLAC_seekable_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); + 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; + + ::OggFLAC__FileDecoder *decoder_; + 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 &); + }; + + /* \} */ + }; }; diff --git a/include/OggFLAC++/encoder.h b/include/OggFLAC++/encoder.h index b92145f..f2917c7 100644 --- a/include/OggFLAC++/encoder.h +++ b/include/OggFLAC++/encoder.h @@ -34,6 +34,8 @@ #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... @@ -55,11 +57,11 @@ * \ingroup oggflacpp * * \brief - * This module describes the encoder layers provided by libOggFLAC++. + * This module describes the three encoder layers provided by libOggFLAC++. * * The libOggFLAC++ encoder classes are object wrappers around their - * counterparts in libOggFLAC. Only the stream encoding layer in - * libOggFLAC is provided here. The interface is very similar; + * counterparts in libOggFLAC. All three encoding 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 @@ -158,12 +160,12 @@ namespace OggFLAC { 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; + virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata) = 0; ::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 void metadata_callback_(const ::OggFLAC__StreamEncoder *encoder, const ::FLAC__StreamMetadata *metadata, void *client_data); // Private and undefined so you can't use them: Stream(const Stream &); @@ -172,6 +174,200 @@ 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_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::SeekableStream::State get_FLAC_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); + 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; + + ::OggFLAC__SeekableStreamEncoder *encoder_; + private: + 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. + * + * \{ + */ + + /** This class wraps the ::OggFLAC__FileEncoder. + */ + class OggFLACPP_API File { + 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_; + }; + + 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_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::SeekableStream::State get_FLAC_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); + protected: + virtual void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate); + + ::OggFLAC__FileEncoder *encoder_; + 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); + + // Private and undefined so you can't use them: + File(const Stream &); + void operator=(const Stream &); + }; + + /* \} */ + }; }; diff --git a/include/OggFLAC/Makefile.am b/include/OggFLAC/Makefile.am index ce88f73..8d710de 100644 --- a/include/OggFLAC/Makefile.am +++ b/include/OggFLAC/Makefile.am @@ -36,5 +36,9 @@ 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 diff --git a/include/OggFLAC/all.h b/include/OggFLAC/all.h index d690700..2f2730b 100644 --- a/include/OggFLAC/all.h +++ b/include/OggFLAC/all.h @@ -38,6 +38,10 @@ #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_encoder.h b/include/OggFLAC/file_encoder.h new file mode 100644 index 0000000..015a7d4 --- /dev/null +++ b/include/OggFLAC/file_encoder.h @@ -0,0 +1,878 @@ +/* libOggFLAC - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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 NULL, 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_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(). + * + * \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. + */ +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 seekable 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_SEEKABLE_STREAM_ENCODER_ERROR. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__SeekableStreamEncoderState + * The seekable stream encoder state. + */ +OggFLAC_API FLAC__SeekableStreamEncoderState OggFLAC__file_encoder_get_FLAC_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_SEEKABLE_STREAM_ENCODER_ERROR + * and the FLAC 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. + */ +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_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. + * \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_encoder.h b/include/OggFLAC/seekable_stream_encoder.h new file mode 100644 index 0000000..1a0cb85 --- /dev/null +++ b/include/OggFLAC/seekable_stream_encoder.h @@ -0,0 +1,853 @@ +/* libOggFLAC - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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/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 + * 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_SEEKABLE_STREAM_ENCODER_ERROR, + /**< An error occurred in the underlying FLAC seekable stream encoder; + * check OggFLAC__stream_encoder_get_FLAC_seekable_stream_encoder_state(). + */ + + OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK, + /**< The encoder was initialized before setting all the required callbacks. */ + + OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, + /**< Memory allocation failed. */ + + 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_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[]; + + +/*********************************************************************** + * + * 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 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 NULL, 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__SeekableStreamEncoder; see FLAC__seekable_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__SeekableStreamEncoder; see FLAC__seekable_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__SeekableStreamEncoder; see FLAC__seekable_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__SeekableStreamEncoder; see FLAC__seekable_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__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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_channels(OggFLAC__SeekableStreamEncoder *encoder, unsigned value); + +/** This is inherited from FLAC__SeekableStreamEncoder; see FLAC__seekable_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__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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_sample_rate(OggFLAC__SeekableStreamEncoder *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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_blocksize(OggFLAC__SeekableStreamEncoder *encoder, unsigned value); + +/** 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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_lpc_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value); + +/** This is inherited from FLAC__SeekableStreamEncoder; see FLAC__seekable_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__SeekableStreamEncoder; see FLAC__seekable_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__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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_escape_coding(OggFLAC__SeekableStreamEncoder *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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(OggFLAC__SeekableStreamEncoder *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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(OggFLAC__SeekableStreamEncoder *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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(OggFLAC__SeekableStreamEncoder *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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(OggFLAC__SeekableStreamEncoder *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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_total_samples_estimate(OggFLAC__SeekableStreamEncoder *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. + */ +OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__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. + */ +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__SeekableStreamEncoder; see + * FLAC__seekable_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 seekable stream encoder. + * Useful when the seekable stream encoder state is + * \c OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_SEEKABLE_STREAM_ENCODER_ERROR. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__SeekableStreamEncoderState + * The FLAC seeekable stream encoder state. + */ +OggFLAC_API FLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_get_FLAC_seekable_stream_encoder_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_SEEKABLE_STREAM_ENCODER_ERROR + * and the FLAC 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 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 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. + * \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_SEEKABLE_STREAM_ENCODER_ERROR + * by getting the FLAC seekable 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__seekable_stream_encoder_get_verify_decoder_error_stats(). + * Useful when the 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 + * \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__SeekableStreamEncoder; see FLAC__seekable_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__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 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__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 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__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 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__SeekableStreamEncoder; see FLAC__seekable_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__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 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__SeekableStreamEncoder; see FLAC__seekable_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__SeekableStreamEncoder; see FLAC__seekable_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__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 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__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 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__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 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__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 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__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 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__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 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__SeekableStreamEncoder; see FLAC__seekable_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__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 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__SeekableStreamEncoder; see FLAC__seekable_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__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 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__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 + * 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 diff --git a/src/libOggFLAC++/Makefile.am b/src/libOggFLAC++/Makefile.am index 10ba4ad..3239133 100644 --- a/src/libOggFLAC++/Makefile.am +++ b/src/libOggFLAC++/Makefile.am @@ -45,5 +45,9 @@ libOggFLAC___la_LDFLAGS = -version-info 0:4:0 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 diff --git a/src/libOggFLAC++/Makefile.lite b/src/libOggFLAC++/Makefile.lite index 0edd3d9..4f3771f 100644 --- a/src/libOggFLAC++/Makefile.lite +++ b/src/libOggFLAC++/Makefile.lite @@ -38,6 +38,10 @@ LIB_NAME = libOggFLAC++ 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 diff --git a/src/libOggFLAC++/file_decoder.cpp b/src/libOggFLAC++/file_decoder.cpp new file mode 100644 index 0000000..678908e --- /dev/null +++ b/src/libOggFLAC++/file_decoder.cpp @@ -0,0 +1,237 @@ +/* libOggFLAC++ - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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" + +namespace OggFLAC { + namespace Decoder { + + File::File(): + decoder_(::OggFLAC__file_decoder_new()) + { } + + 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__ASSERT(0 != decoder_); + return (bool)::OggFLAC__file_decoder_set_md5_checking(decoder_, value); + } + + bool File::set_filename(const char *value) + { + 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_)); + } + + FLAC::Decoder::File::State File::get_FLAC_file_decoder_state() const + { + FLAC__ASSERT(is_valid()); + return FLAC::Decoder::File::State(::OggFLAC__file_decoder_get_FLAC_file_decoder_state(decoder_)); + } + + FLAC::Decoder::SeekableStream::State File::get_FLAC_seekable_stream_decoder_state() const + { + FLAC__ASSERT(is_valid()); + return FLAC::Decoder::SeekableStream::State(::OggFLAC__file_decoder_get_FLAC_seekable_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(client_data); + FLAC__ASSERT(0 != instance); + return instance->write_callback(frame, buffer); + } + + void File::metadata_callback_(const ::OggFLAC__FileDecoder *decoder, const ::FLAC__StreamMetadata *metadata, void *client_data) + { + (void) decoder; + FLAC__ASSERT(0 != client_data); + File *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + instance->metadata_callback(metadata); + } + + void File::error_callback_(const ::OggFLAC__FileDecoder *decoder, ::FLAC__StreamDecoderErrorStatus status, void *client_data) + { + (void) decoder; + FLAC__ASSERT(0 != client_data); + File *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + instance->error_callback(status); + } + + }; +}; diff --git a/src/libOggFLAC++/file_encoder.cpp b/src/libOggFLAC++/file_encoder.cpp new file mode 100644 index 0000000..74fe683 --- /dev/null +++ b/src/libOggFLAC++/file_encoder.cpp @@ -0,0 +1,354 @@ +/* libOggFLAC++ - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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" + +namespace OggFLAC { + namespace Encoder { + + File::File(): + encoder_(::OggFLAC__file_encoder_new()) + { } + + File::~File() + { + if(0 != encoder_) { + ::OggFLAC__file_encoder_finish(encoder_); + ::OggFLAC__file_encoder_delete(encoder_); + } + } + + bool File::set_serial_number(long value) + { + FLAC__ASSERT(is_valid()); + return (bool)::OggFLAC__file_encoder_set_serial_number(encoder_, value); + } + + 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__ASSERT(is_valid()); + return (bool)::OggFLAC__file_encoder_set_do_mid_side_stereo(encoder_, value); + } + + bool File::set_loose_mid_side_stereo(bool value) + { + FLAC__ASSERT(is_valid()); + return (bool)::OggFLAC__file_encoder_set_loose_mid_side_stereo(encoder_, value); + } + + bool File::set_channels(unsigned value) + { + 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_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::SeekableStream::State File::get_FLAC_seekable_stream_encoder_state() const + { + FLAC__ASSERT(is_valid()); + return FLAC::Encoder::SeekableStream::State(::OggFLAC__file_encoder_get_FLAC_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 File::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; + } + + 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)encoder; + FLAC__ASSERT(0 != client_data); + File *instance = reinterpret_cast(client_data); + FLAC__ASSERT(0 != instance); + instance->progress_callback(bytes_written, samples_written, frames_written, total_frames_estimate); + } + + }; +}; diff --git a/src/libOggFLAC++/libOggFLAC++_dynamic.dsp b/src/libOggFLAC++/libOggFLAC++_dynamic.dsp index 86aa879..1c13d34 100644 --- a/src/libOggFLAC++/libOggFLAC++_dynamic.dsp +++ b/src/libOggFLAC++/libOggFLAC++_dynamic.dsp @@ -92,6 +92,22 @@ LINK32=link.exe # PROP Default_Filter "cpp" # Begin Source File +SOURCE=.\file_decoder.cpp +# End Source File +# Begin Source File + +SOURCE=.\file_encoder.cpp +# End Source File +# Begin Source File + +SOURCE=.\seekable_stream_decoder.cpp +# End Source File +# Begin Source File + +SOURCE=.\seekable_stream_encoder.cpp +# End Source File +# Begin Source File + SOURCE=.\stream_decoder.cpp # End Source File # Begin Source File diff --git a/src/libOggFLAC++/libOggFLAC++_static.dsp b/src/libOggFLAC++/libOggFLAC++_static.dsp index 6178c25..0331571 100644 --- a/src/libOggFLAC++/libOggFLAC++_static.dsp +++ b/src/libOggFLAC++/libOggFLAC++_static.dsp @@ -85,6 +85,22 @@ LIB32=link.exe -lib # PROP Default_Filter "cpp" # Begin Source File +SOURCE=.\file_decoder.cpp +# End Source File +# Begin Source File + +SOURCE=.\file_encoder.cpp +# End Source File +# Begin Source File + +SOURCE=.\seekable_stream_decoder.cpp +# End Source File +# Begin Source File + +SOURCE=.\seekable_stream_encoder.cpp +# End Source File +# Begin Source File + SOURCE=.\stream_decoder.cpp # End Source File # Begin Source File diff --git a/src/libOggFLAC++/seekable_stream_decoder.cpp b/src/libOggFLAC++/seekable_stream_decoder.cpp new file mode 100644 index 0000000..5d952aa --- /dev/null +++ b/src/libOggFLAC++/seekable_stream_decoder.cpp @@ -0,0 +1,287 @@ +/* libOggFLAC++ - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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" + +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_)); + } + + FLAC::Decoder::SeekableStream::State SeekableStream::get_FLAC_seekable_stream_decoder_state() const + { + FLAC__ASSERT(is_valid()); + return FLAC::Decoder::SeekableStream::State(::OggFLAC__seekable_stream_decoder_get_FLAC_seekable_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); + } + + ::FLAC__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(client_data); + FLAC__ASSERT(0 != instance); + return instance->read_callback(buffer, bytes); + } + + ::FLAC__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(client_data); + FLAC__ASSERT(0 != instance); + return instance->seek_callback(absolute_byte_offset); + } + + ::FLAC__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(client_data); + FLAC__ASSERT(0 != instance); + return instance->tell_callback(absolute_byte_offset); + } + + ::FLAC__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(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(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(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(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(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 new file mode 100644 index 0000000..2b6b8b0 --- /dev/null +++ b/src/libOggFLAC++/seekable_stream_encoder.cpp @@ -0,0 +1,357 @@ +/* libOggFLAC++ - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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" + +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_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::SeekableStream::State SeekableStream::get_FLAC_seekable_stream_encoder_state() const + { + FLAC__ASSERT(is_valid()); + return FLAC::Encoder::SeekableStream::State(::OggFLAC__seekable_stream_encoder_get_FLAC_seekable_stream_encoder_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_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); + } + + ::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(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(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(client_data); + FLAC__ASSERT(0 != instance); + return instance->write_callback(buffer, bytes, samples, current_frame); + } + + }; +}; diff --git a/src/libOggFLAC/Makefile.am b/src/libOggFLAC/Makefile.am index 6fa7211..2397610 100644 --- a/src/libOggFLAC/Makefile.am +++ b/src/libOggFLAC/Makefile.am @@ -50,5 +50,11 @@ libOggFLAC_la_LIBADD = @OGG_LIBS@ ../libFLAC/libFLAC.la libOggFLAC_la_LDFLAGS = -version-info 1:2:0 libOggFLAC_la_SOURCES = \ + file_decoder.c \ + file_encoder.c \ + ogg_decoder_aspect.c \ + ogg_encoder_aspect.c \ + seekable_stream_decoder.c \ + seekable_stream_encoder.c \ stream_decoder.c \ stream_encoder.c diff --git a/src/libOggFLAC/Makefile.lite b/src/libOggFLAC/Makefile.lite index ccc5dc5..2f4e9a1 100644 --- a/src/libOggFLAC/Makefile.lite +++ b/src/libOggFLAC/Makefile.lite @@ -48,6 +48,12 @@ INCLUDES = -I./include -I$(topdir)/include -I$(HOME)/local/include DEBUG_CFLAGS = SRCS_C = \ + file_decoder.c \ + file_encoder.c \ + ogg_decoder_aspect.c \ + ogg_encoder_aspect.c \ + seekable_stream_decoder.c \ + seekable_stream_encoder.c \ stream_decoder.c \ stream_encoder.c diff --git a/src/libOggFLAC/file_encoder.c b/src/libOggFLAC/file_encoder.c new file mode 100644 index 0000000..da465d2 --- /dev/null +++ b/src/libOggFLAC/file_encoder.c @@ -0,0 +1,783 @@ +/* libOggFLAC - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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 +#include /* for malloc() */ +#include /* for strlen(), strcpy() */ +#include "FLAC/assert.h" +#include "OggFLAC/seekable_stream_encoder.h" +#include "protected/file_encoder.h" + +/*********************************************************************** + * + * 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 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 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; + + 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_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__SeekableStreamEncoderState OggFLAC__file_encoder_get_FLAC_seekable_stream_encoder_state(const OggFLAC__FileEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + return OggFLAC__seekable_stream_encoder_get_FLAC_seekable_stream_encoder_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; +} + +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(fseek(file_encoder->private_->file, (long)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; + long offset; + + (void)encoder; + + FLAC__ASSERT(0 != file_encoder); + + offset = ftell(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, (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; + 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, current_frame+1, file_encoder->private_->total_frames_estimate, file_encoder->private_->client_data); + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; + } + else + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; +} diff --git a/src/libOggFLAC/include/protected/Makefile.am b/src/libOggFLAC/include/protected/Makefile.am index 2235acc..fbe099f 100644 --- a/src/libOggFLAC/include/protected/Makefile.am +++ b/src/libOggFLAC/include/protected/Makefile.am @@ -31,6 +31,8 @@ noinst_HEADERS = \ all.h \ file_decoder.h \ + file_encoder.h \ seekable_stream_decoder.h \ + seekable_stream_encoder.h \ stream_decoder.h \ stream_encoder.h diff --git a/src/libOggFLAC/include/protected/all.h b/src/libOggFLAC/include/protected/all.h index 1e25c2b..7d7e2b0 100644 --- a/src/libOggFLAC/include/protected/all.h +++ b/src/libOggFLAC/include/protected/all.h @@ -33,7 +33,9 @@ #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_encoder.h b/src/libOggFLAC/include/protected/file_encoder.h new file mode 100644 index 0000000..005a865 --- /dev/null +++ b/src/libOggFLAC/include/protected/file_encoder.h @@ -0,0 +1,41 @@ +/* libOggFLAC - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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_encoder.h b/src/libOggFLAC/include/protected/seekable_stream_encoder.h new file mode 100644 index 0000000..c869399 --- /dev/null +++ b/src/libOggFLAC/include/protected/seekable_stream_encoder.h @@ -0,0 +1,43 @@ +/* libOggFLAC - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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; +} OggFLAC__SeekableStreamEncoderProtected; + +#endif diff --git a/src/libOggFLAC/libOggFLAC_dynamic.dsp b/src/libOggFLAC/libOggFLAC_dynamic.dsp index 7632bde..d77563c 100644 --- a/src/libOggFLAC/libOggFLAC_dynamic.dsp +++ b/src/libOggFLAC/libOggFLAC_dynamic.dsp @@ -92,6 +92,30 @@ LINK32=link.exe # PROP Default_Filter "c" # Begin Source File +SOURCE=.\file_decoder.c +# End Source File +# Begin Source File + +SOURCE=.\file_encoder.c +# End Source File +# Begin Source File + +SOURCE=.\ogg_decoder_aspect.c +# End Source File +# Begin Source File + +SOURCE=.\ogg_encoder_aspect.c +# End Source File +# Begin Source File + +SOURCE=.\seekable_stream_decoder.c +# End Source File +# Begin Source File + +SOURCE=.\seekable_stream_encoder.c +# End Source File +# Begin Source File + SOURCE=.\stream_decoder.c # End Source File # Begin Source File @@ -102,6 +126,18 @@ SOURCE=.\stream_encoder.c # Begin Group "Private Header Files" # PROP Default_Filter "" +# Begin Source File + +SOURCE=.\include\private\all.h +# End Source File +# Begin Source File + +SOURCE=.\include\private\ogg_decoder_aspect.h +# End Source File +# Begin Source File + +SOURCE=.\include\private\ogg_encoder_aspect.h +# End Source File # End Group # Begin Group "Protected Header Files" @@ -112,6 +148,22 @@ SOURCE=.\include\protected\all.h # End Source File # Begin Source File +SOURCE=.\include\protected\file_decoder.h +# End Source File +# Begin Source File + +SOURCE=.\include\protected\file_encoder.h +# End Source File +# Begin Source File + +SOURCE=.\include\protected\seekable_stream_decoder.h +# End Source File +# Begin Source File + +SOURCE=.\include\protected\seekable_stream_encoder.h +# End Source File +# Begin Source File + SOURCE=.\include\protected\stream_decoder.h # End Source File # Begin Source File @@ -132,6 +184,22 @@ SOURCE=..\..\include\OggFLAC\export.h # End Source File # Begin Source File +SOURCE=..\..\include\OggFLAC\file_decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\OggFLAC\file_encoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\OggFLAC\seekable_stream_decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\OggFLAC\seekable_stream_encoder.h +# End Source File +# Begin Source File + SOURCE=..\..\include\OggFLAC\stream_decoder.h # End Source File # Begin Source File diff --git a/src/libOggFLAC/libOggFLAC_static.dsp b/src/libOggFLAC/libOggFLAC_static.dsp index cb2b805..db06fc7 100644 --- a/src/libOggFLAC/libOggFLAC_static.dsp +++ b/src/libOggFLAC/libOggFLAC_static.dsp @@ -85,6 +85,30 @@ LIB32=link.exe -lib # PROP Default_Filter "c" # Begin Source File +SOURCE=.\file_decoder.c +# End Source File +# Begin Source File + +SOURCE=.\file_encoder.c +# End Source File +# Begin Source File + +SOURCE=.\ogg_decoder_aspect.c +# End Source File +# Begin Source File + +SOURCE=.\ogg_encoder_aspect.c +# End Source File +# Begin Source File + +SOURCE=.\seekable_stream_decoder.c +# End Source File +# Begin Source File + +SOURCE=.\seekable_stream_encoder.c +# End Source File +# Begin Source File + SOURCE=.\stream_decoder.c # End Source File # Begin Source File @@ -95,6 +119,18 @@ SOURCE=.\stream_encoder.c # Begin Group "Private Header Files" # PROP Default_Filter "" +# Begin Source File + +SOURCE=.\include\private\all.h +# End Source File +# Begin Source File + +SOURCE=.\include\private\ogg_decoder_aspect.h +# End Source File +# Begin Source File + +SOURCE=.\include\private\ogg_encoder_aspect.h +# End Source File # End Group # Begin Group "Protected Header Files" @@ -105,6 +141,22 @@ SOURCE=.\include\protected\all.h # End Source File # Begin Source File +SOURCE=.\include\protected\file_decoder.h +# End Source File +# Begin Source File + +SOURCE=.\include\protected\file_encoder.h +# End Source File +# Begin Source File + +SOURCE=.\include\protected\seekable_stream_decoder.h +# End Source File +# Begin Source File + +SOURCE=.\include\protected\seekable_stream_encoder.h +# End Source File +# Begin Source File + SOURCE=.\include\protected\stream_decoder.h # End Source File # Begin Source File @@ -125,6 +177,22 @@ SOURCE=..\..\include\OggFLAC\export.h # End Source File # Begin Source File +SOURCE=..\..\include\OggFLAC\file_decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\OggFLAC\file_encoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\OggFLAC\seekable_stream_decoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\include\OggFLAC\seekable_stream_encoder.h +# End Source File +# Begin Source File + SOURCE=..\..\include\OggFLAC\stream_decoder.h # End Source File # Begin Source File diff --git a/src/libOggFLAC/seekable_stream_encoder.c b/src/libOggFLAC/seekable_stream_encoder.c new file mode 100644 index 0000000..515c004 --- /dev/null +++ b/src/libOggFLAC/seekable_stream_encoder.c @@ -0,0 +1,732 @@ +/* libOggFLAC - Free Lossless Audio Codec + Ogg library + * Copyright (C) 2002,2003 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 +#include /* for calloc() */ +#include "FLAC/assert.h" +#include "OggFLAC/seekable_stream_encoder.h" +#include "protected/seekable_stream_encoder.h" + +/*********************************************************************** + * + * 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_(OggFLAC__SeekableStreamEncoder *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 OggFLAC__SeekableStreamEncoderPrivate { + OggFLAC__SeekableStreamEncoderSeekCallback seek_callback; + OggFLAC__SeekableStreamEncoderTellCallback tell_callback; + OggFLAC__SeekableStreamEncoderWriteCallback write_callback; + void *client_data; + FLAC__SeekableStreamEncoder *FLAC_seekable_stream_encoder; +} 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_SEEKABLE_STREAM_ENCODER_ERROR", + "OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK", + "OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR", + "OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED", + "OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED" +}; + + +/*********************************************************************** + * + * 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_seekable_stream_encoder = FLAC__seekable_stream_encoder_new(); + if(0 == encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + + (void)OggFLAC__seekable_stream_encoder_finish(encoder); + + FLAC__seekable_stream_encoder_delete(encoder->private_->FLAC_seekable_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; + + FLAC__seekable_stream_encoder_set_seek_callback(encoder->private_->FLAC_seekable_stream_encoder, seek_callback_); + FLAC__seekable_stream_encoder_set_tell_callback(encoder->private_->FLAC_seekable_stream_encoder, tell_callback_); + FLAC__seekable_stream_encoder_set_write_callback(encoder->private_->FLAC_seekable_stream_encoder, write_callback_); + FLAC__seekable_stream_encoder_set_client_data(encoder->private_->FLAC_seekable_stream_encoder, encoder); + + if(FLAC__seekable_stream_encoder_init(encoder->private_->FLAC_seekable_stream_encoder) != FLAC__SEEKABLE_STREAM_ENCODER_OK) + return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_SEEKABLE_STREAM_ENCODER_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_seekable_stream_encoder); + + FLAC__seekable_stream_encoder_finish(encoder->private_->FLAC_seekable_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_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_verify(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_streamable_subset(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_channels(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_bits_per_sample(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_sample_rate(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_blocksize(encoder->private_->FLAC_seekable_stream_encoder, value); +} + +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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_max_lpc_order(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_do_escape_coding(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_total_samples_estimate(encoder->private_->FLAC_seekable_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_seekable_stream_encoder); + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_metadata(encoder->private_->FLAC_seekable_stream_encoder, metadata, num_blocks); +} + +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__seekable_stream_encoder_disable_constant_subframes(encoder->private_->FLAC_seekable_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__seekable_stream_encoder_disable_fixed_subframes(encoder->private_->FLAC_seekable_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__seekable_stream_encoder_disable_verbatim_subframes(encoder->private_->FLAC_seekable_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__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_get_FLAC_seekable_stream_encoder_state(const OggFLAC__SeekableStreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return FLAC__seekable_stream_encoder_get_state(encoder->private_->FLAC_seekable_stream_encoder); +} + +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_); + return FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder->private_->FLAC_seekable_stream_encoder); +} + +OggFLAC_API const char *OggFLAC__seekable_stream_encoder_get_resolved_state_string(const OggFLAC__SeekableStreamEncoder *encoder) +{ + if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_SEEKABLE_STREAM_ENCODER_ERROR) + return OggFLAC__SeekableStreamEncoderStateString[encoder->protected_->state]; + else + return FLAC__seekable_stream_encoder_get_resolved_state_string(encoder->private_->FLAC_seekable_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__seekable_stream_encoder_get_verify_decoder_error_stats(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_verify(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_streamable_subset(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_channels(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_bits_per_sample(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_sample_rate(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_blocksize(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_max_lpc_order(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_do_escape_coding(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_seekable_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_); + return FLAC__seekable_stream_encoder_process(encoder->private_->FLAC_seekable_stream_encoder, buffer, samples); +} + +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_); + return FLAC__seekable_stream_encoder_process_interleaved(encoder->private_->FLAC_seekable_stream_encoder, buffer, samples); +} + +/*********************************************************************** + * + * Private class methods + * + ***********************************************************************/ + +void set_defaults_(OggFLAC__SeekableStreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + + encoder->private_->seek_callback = 0; + encoder->private_->tell_callback = 0; + encoder->private_->write_callback = 0; + encoder->private_->client_data = 0; + OggFLAC__ogg_encoder_aspect_set_defaults(&encoder->protected_->ogg_encoder_aspect); +} + +FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const FLAC__SeekableStreamEncoder *unused, FLAC__uint64 absolute_byte_offset, void *client_data) +{ + OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data; + + (void)unused; + FLAC__ASSERT(encoder->private_->FLAC_seekable_stream_encoder == unused); + + return encoder->private_->seek_callback(encoder, absolute_byte_offset, encoder->private_->client_data); +} + +FLAC__SeekableStreamEncoderTellStatus tell_callback_(const FLAC__SeekableStreamEncoder *unused, FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data; + + (void)unused; + FLAC__ASSERT(encoder->private_->FLAC_seekable_stream_encoder == unused); + + return encoder->private_->tell_callback(encoder, absolute_byte_offset, encoder->private_->client_data); +} + +FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__SeekableStreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data) +{ + OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data; + const FLAC__uint64 total_samples_estimate = FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_seekable_stream_encoder); + + (void)unused; + FLAC__ASSERT(encoder->private_->FLAC_seekable_stream_encoder == unused); + + 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); +} diff --git a/src/test_libOggFLAC++/decoders.cpp b/src/test_libOggFLAC++/decoders.cpp index 236a244..32020c2 100644 --- a/src/test_libOggFLAC++/decoders.cpp +++ b/src/test_libOggFLAC++/decoders.cpp @@ -795,16 +795,1402 @@ 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 + ::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(::fseek(file_, (long)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) +{ + if(error_occurred_) + return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + + long offset = ::ftell(file_); + *absolute_byte_offset = (FLAC__uint64)offset; + + if(offset < 0) { + error_occurred_ = true; + return ::FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + } + + return ::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)oggflacfilesize_; + 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)((::OggFLAC__SeekableStreamDecoderState)state), state.as_cstring()); + if(state == ::OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) { + FLAC::Decoder::SeekableStream::State state_ = get_FLAC_seekable_stream_decoder_state(); + printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state_), state_.as_cstring()); + if(state_ == ::FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + 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(::fseek(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_FLAC_seekable_stream_decoder_state()... "); + FLAC::Decoder::SeekableStream::State state_ = decoder->get_FLAC_seekable_stream_decoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state_), state_.as_cstring()); + + printf("testing get_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\n"); + 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(::fseek(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 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_FLAC_FILE_DECODER_ERROR) { + FLAC::Decoder::File::State state_ = get_FLAC_file_decoder_state(); + printf(" FLAC file decoder state = %u (%s)\n", (unsigned)((::FLAC__FileDecoderState)state_), state_.as_cstring()); + if(state_ == ::OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR) { + FLAC::Decoder::SeekableStream::State state__ = get_FLAC_seekable_stream_decoder_state(); + printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state__), state__.as_cstring()); + if(state__ == ::FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + 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_FLAC_file_decoder_state()... "); + FLAC::Decoder::File::State state_ = decoder->get_FLAC_file_decoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__FileDecoderState)state_), state_.as_cstring()); + + printf("testing get_FLAC_seekable_stream_decoder_state()... "); + FLAC::Decoder::SeekableStream::State state__ = decoder->get_FLAC_seekable_stream_decoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__SeekableStreamDecoderState)state__), state__.as_cstring()); + + printf("testing get_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_++] = &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_()) return false; if(!test_stream_decoder()) return false; + if(!test_seekable_stream_decoder()) + return false; + + if(!test_file_decoder()) + return false; + (void) grabbag__file_remove_file(oggflacfilename_); + free_metadata_blocks_(); return true; diff --git a/src/test_libOggFLAC++/encoders.cpp b/src/test_libOggFLAC++/encoders.cpp index 0a30f71..d571681 100644 --- a/src/test_libOggFLAC++/encoders.cpp +++ b/src/test_libOggFLAC++/encoders.cpp @@ -30,6 +30,7 @@ extern "C" { 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 *oggflacfilename_ = "metadata.ogg"; static void init_metadata_blocks_() { @@ -48,7 +49,7 @@ public: // from OggFLAC::Encoder::Stream ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame); - void metadata_callback(const FLAC__StreamMetadata *metadata); + void metadata_callback(const ::FLAC__StreamMetadata *metadata); bool die(const char *msg = 0) const; }; @@ -60,7 +61,7 @@ public: return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK; } -void StreamEncoder::metadata_callback(const FLAC__StreamMetadata *metadata) +void StreamEncoder::metadata_callback(const ::FLAC__StreamMetadata *metadata) { (void)metadata; } @@ -380,6 +381,714 @@ static bool test_stream_encoder() return true; } +class SeekableStreamEncoder : public OggFLAC::Encoder::SeekableStream { +public: + SeekableStreamEncoder(): OggFLAC::Encoder::SeekableStream() { } + ~SeekableStreamEncoder() { } + + // from OggFLAC::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) +{ + (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_SEEKABLE_STREAM_ENCODER_ERROR) { + FLAC::Encoder::SeekableStream::State state_ = get_FLAC_seekable_stream_encoder_state(); + printf(" FLAC 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_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() +{ + 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_seekable_stream_encoder_state()... "); + FLAC::Encoder::SeekableStream::State state_ = encoder->get_FLAC_seekable_stream_encoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__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; +} + +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_SEEKABLE_STREAM_ENCODER_ERROR) { + FLAC::Encoder::SeekableStream::State state__ = get_FLAC_seekable_stream_encoder_state(); + printf(" FLAC 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_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_seekable_stream_encoder_state()... "); + FLAC::Encoder::SeekableStream::State state__ = encoder->get_FLAC_seekable_stream_encoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__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_(); @@ -387,6 +1096,12 @@ bool test_encoders() if(!test_stream_encoder()) return false; + if(!test_seekable_stream_encoder()) + return false; + + if(!test_file_encoder()) + return false; + free_metadata_blocks_(); return true; diff --git a/src/test_libOggFLAC/decoders.c b/src/test_libOggFLAC/decoders.c index 1204f7f..7238311 100644 --- a/src/test_libOggFLAC/decoders.c +++ b/src/test_libOggFLAC/decoders.c @@ -20,6 +20,8 @@ #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 @@ -34,6 +36,9 @@ typedef struct { 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; + static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_; static FLAC__StreamMetadata *expected_metadata_sequence_[8]; static unsigned num_expected_; @@ -64,6 +69,54 @@ 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_FLAC_SEEKABLE_STREAM_DECODER_ERROR) { + FLAC__SeekableStreamDecoderState state_ = OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder); + printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)state_, FLAC__SeekableStreamDecoderStateString[state_]); + if(state_ == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + 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_FLAC_FILE_DECODER_ERROR) { + FLAC__FileDecoderState state_ = OggFLAC__file_decoder_get_FLAC_file_decoder_state(decoder); + printf(" FLAC file decoder state = %u (%s)\n", (unsigned)state_, FLAC__FileDecoderStateString[state_]); + if(state_ == FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) { + FLAC__SeekableStreamDecoderState state__ = OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder); + printf(" FLAC seekable stream decoder state = %u (%s)\n", (unsigned)state__, FLAC__SeekableStreamDecoderStateString[state__]); + if(state__ == FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) { + 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_); @@ -243,6 +296,7 @@ static FLAC__bool test_stream_decoder() { OggFLAC__StreamDecoder *decoder; OggFLAC__StreamDecoderState state; + FLAC__StreamDecoderState fstate; stream_decoder_client_data_struct decoder_client_data; printf("\n+++ libOggFLAC unit test: OggFLAC__StreamDecoder\n\n"); @@ -326,6 +380,10 @@ static FLAC__bool test_stream_decoder() state = OggFLAC__stream_decoder_get_state(decoder); printf("returned state = %u (%s)... OK\n", state, OggFLAC__StreamDecoderStateString[state]); + printf("testing OggFLAC__stream_decoder_get_FLAC_stream_decoder_state()... "); + fstate = OggFLAC__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; @@ -742,13 +800,1286 @@ static FLAC__bool test_stream_decoder() return true; } -FLAC__bool test_decoders() +static FLAC__SeekableStreamDecoderReadStatus seekable_stream_decoder_read_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) { - init_metadata_blocks_(); - if(!generate_file_()) + (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 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 FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + } + + if(dcd->error_occurred) + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + + if(fseek(dcd->file, (long)absolute_byte_offset, SEEK_SET) < 0) { + dcd->error_occurred = true; + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; + } + + return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; +} + +static FLAC__SeekableStreamDecoderTellStatus seekable_stream_decoder_tell_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + seekable_stream_decoder_client_data_struct *dcd = (seekable_stream_decoder_client_data_struct*)client_data; + long 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 = ftell(dcd->file); + *absolute_byte_offset = (FLAC__uint64)offset; + + if(offset < 0) { + dcd->error_occurred = true; + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR; + } + + return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; +} + +static FLAC__SeekableStreamDecoderLengthStatus seekable_stream_decoder_length_callback_(const OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) +{ + 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)oggflacfilesize_; + return FLAC__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) +{ + 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"); + + dcd->current_metadata_number = 0; + + if(fseek(dcd->file, 0, SEEK_SET) < 0) { + printf("FAILED rewinding input, errno = %d\n", errno); return false; + } - if(!test_stream_decoder()) + 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; + FLAC__SeekableStreamDecoderState fsstate; + 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_FLAC_seekable_stream_decoder_state()... "); + fsstate = OggFLAC__seekable_stream_decoder_get_FLAC_seekable_stream_decoder_state(decoder); + printf("returned state = %u (%s)... OK\n", fsstate, FLAC__SeekableStreamDecoderStateString[fsstate]); + + printf("testing OggFLAC__seekable_stream_decoder_get_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\n"); + 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(fseek(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_++] = &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 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_++] = &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 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_++] = &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 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_++] = &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 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_++] = &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 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_++] = &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 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; + FLAC__FileDecoderState ffstate; + FLAC__SeekableStreamDecoderState fsstate; + 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_FLAC_file_decoder_state()... "); + ffstate = OggFLAC__file_decoder_get_FLAC_file_decoder_state(decoder); + printf("returned state = %u (%s)... OK\n", ffstate, FLAC__FileDecoderStateString[ffstate]); + + printf("testing OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state()... "); + fsstate = OggFLAC__file_decoder_get_FLAC_seekable_stream_decoder_state(decoder); + printf("returned state = %u (%s)... OK\n", fsstate, FLAC__SeekableStreamDecoderStateString[fsstate]); + + printf("testing OggFLAC__file_decoder_get_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_++] = &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 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_++] = &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 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_++] = &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 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_++] = &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 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_++] = &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 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_++] = &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 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_()) + return false; + + if(!test_stream_decoder()) + return false; + + if(!test_seekable_stream_decoder()) + return false; + + if(!test_file_decoder()) return false; (void) grabbag__file_remove_file(oggflacfilename_); diff --git a/src/test_libOggFLAC/encoders.c b/src/test_libOggFLAC/encoders.c index 40c06fa..f4e783e 100644 --- a/src/test_libOggFLAC/encoders.c +++ b/src/test_libOggFLAC/encoders.c @@ -20,6 +20,8 @@ #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 @@ -53,6 +55,62 @@ 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) +{ + 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_SEEKABLE_STREAM_ENCODER_ERROR) { + FLAC__SeekableStreamEncoderState state_ = OggFLAC__seekable_stream_encoder_get_FLAC_seekable_stream_encoder_state(encoder); + printf(" FLAC seekable stream encoder state = %u (%s)\n", (unsigned)state_, FLAC__SeekableStreamEncoderStateString[state_]); + if(state_ == FLAC__SEEKABLE_STREAM_ENCODER_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; +} + +static FLAC__bool die_f_(const char *msg, const OggFLAC__FileEncoder *encoder) +{ + 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_SEEKABLE_STREAM_ENCODER_ERROR) { + FLAC__SeekableStreamEncoderState state__ = OggFLAC__file_encoder_get_FLAC_seekable_stream_encoder_state(encoder); + printf(" FLAC seekable stream encoder state = %u (%s)\n", (unsigned)state__, FLAC__SeekableStreamEncoderStateString[state__]); + if(state__ == FLAC__SEEKABLE_STREAM_ENCODER_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]); + } + } + } + } + + return false; +} + static void init_metadata_blocks_() { mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_); @@ -79,7 +137,7 @@ static FLAC__bool test_stream_encoder() { OggFLAC__StreamEncoder *encoder; OggFLAC__StreamEncoderState state; - FLAC__StreamEncoderState state_; + FLAC__StreamEncoderState fstate; FLAC__StreamDecoderState dstate; FLAC__int32 samples[1024]; FLAC__int32 *samples_array[1]; @@ -217,8 +275,8 @@ static FLAC__bool test_stream_encoder() printf("returned state = %u (%s)... OK\n", (unsigned)state, OggFLAC__StreamEncoderStateString[state]); printf("testing OggFLAC__stream_encoder_get_FLAC_stream_encoder_state()... "); - state_ = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(encoder); - printf("returned state = %u (%s)... OK\n", (unsigned)state_, FLAC__StreamEncoderStateString[state_]); + fstate = OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)fstate, FLAC__StreamEncoderStateString[fstate]); printf("testing OggFLAC__stream_encoder_get_verify_decoder_state()... "); dstate = OggFLAC__stream_encoder_get_verify_decoder_state(encoder); @@ -381,6 +439,661 @@ static FLAC__bool test_stream_encoder() return true; } +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)absolute_byte_offset, (void)client_data; + 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__SeekableStreamEncoderState fsstate; + 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_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_seekable_stream_encoder_state()... "); + fsstate = OggFLAC__seekable_stream_encoder_get_FLAC_seekable_stream_encoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)fsstate, FLAC__SeekableStreamEncoderStateString[fsstate]); + + 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__SeekableStreamEncoderState fsstate; + 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_seekable_stream_encoder_state()... "); + fsstate = OggFLAC__file_encoder_get_FLAC_seekable_stream_encoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)fsstate, FLAC__SeekableStreamEncoderStateString[fsstate]); + + 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_(); @@ -388,6 +1101,12 @@ FLAC__bool test_encoders() if(!test_stream_encoder()) return false; + if(!test_seekable_stream_encoder()) + return false; + + if(!test_file_encoder()) + return false; + (void) grabbag__file_remove_file(oggflacfilename_); free_metadata_blocks_(); -- 2.7.4