bool is_valid() const;
inline operator bool() const { return is_valid(); }
+ bool set_serial_number(long value);
bool set_metadata_respond(::FLAC__MetadataType type);
bool set_metadata_respond_application(const FLAC__byte id[4]);
bool set_metadata_respond_all();
bool 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);
*
***********************************************************************/
+/*@@@inherit set_serial_number*/
+
/** Set the "MD5 signature checking" flag.
* This is inherited from FLAC__FileDecoder; see
* FLAC__file_decoder_set_md5_checking().
* argument.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* Useful when the file decoder state is
* \c OggFLAC__FILE_DECODER_FLAC_FILE_DECODER_ERROR.
*
- * \param decoder An decoder instance to query.
+ * \param decoder A decoder instance to query.
* \assert
* \code decoder != NULL \endcode
* \retval FLAC__FileDecoderState
* \c OggFLAC__FILE_DECODER_FLAC_FILE_DECODER_ERROR and the FLAC file decoder state is
* \c FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR.
*
- * \param decoder An decoder instance to query.
+ * \param decoder A decoder instance to query.
* \assert
* \code decoder != NULL \endcode
* \retval FLAC__SeekableStreamDecoderState
* \c FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR and the
* FLAC seekable stream decoder state is \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR.
*
- * \param decoder An decoder instance to query.
+ * \param decoder A decoder instance to query.
* \assert
* \code decoder != NULL \endcode
* \retval FLAC__StreamDecoderState
*
***********************************************************************/
+/*@@@inherit set_serial_number*/
+
/** Set the "MD5 signature checking" flag.
* This is inherited from FLAC__SeekableStreamDecoder; see
* FLAC__seekable_stream_decoder_set_md5_checking().
* The callback is mandatory and must be set before initialization.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* The callback is mandatory and must be set before initialization.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* The callback is mandatory and must be set before initialization.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* The callback is mandatory and must be set before initialization.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* argument.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* Useful when the seekable stream decoder state is
* \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR.
*
- * \param decoder An decoder instance to query.
+ * \param decoder A decoder instance to query.
* \assert
* \code decoder != NULL \endcode
* \retval FLAC__SeekableStreamDecoderState
* \c OggFLAC__SEEKABLE_STREAM_DECODER_FLAC_SEEKABLE_STREAM_DECODER_ERROR and the
* FLAC seekable stream decoder state is \c FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR
*
- * \param decoder An decoder instance to query.
+ * \param decoder A decoder instance to query.
* \assert
* \code decoder != NULL \endcode
* \retval FLAC__StreamDecoderState
* The callback is mandatory and must be set before initialization.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* The callback is mandatory and must be set before initialization.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* The callback is mandatory and must be set before initialization.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* The callback is mandatory and must be set before initialization.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
* argument.
*
* \default \c NULL
- * \param decoder An decoder instance to set.
+ * \param decoder A decoder instance to set.
* \param value See above.
* \assert
* \code decoder != NULL \endcode
*/
FLAC__bool OggFLAC__stream_decoder_set_client_data(OggFLAC__StreamDecoder *decoder, void *value);
+/** Set the serial number for the Ogg stream.
+ * The default behavior is to use the serial number of the first Ogg
+ * page. Setting a serial number here will explicitly define which
+ * stream is to be decoded.
+ *
+ * \default \c use serial number of first page
+ * \param decoder A decoder instance to set.
+ * \param serial_number See above.
+ * \assert
+ * \code decoder != NULL \endcode
+ * \retval FLAC__bool
+ * \c false if the decoder is already initialized, else \c true.
+ */
+FLAC__bool OggFLAC__stream_decoder_set_serial_number(OggFLAC__StreamDecoder *decoder, long serial_number);
+
/** Direct the decoder to pass on all metadata blocks of type \a type.
* This is inherited from FLAC__StreamDecoder; see FLAC__stream_decoder_set_metadata_respond()
*
* Useful when the stream decoder state is
* \c OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR.
*
- * \param decoder An decoder instance to query.
+ * \param decoder A decoder instance to query.
* \assert
* \code decoder != NULL \endcode
* \retval FLAC__StreamDecoderState
*
***********************************************************************/
+/** 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.
+ */
+FLAC__bool OggFLAC__stream_encoder_set_serial_number(OggFLAC__StreamEncoder *encoder, long serial_number);
+
/** This is inherited from FLAC__StreamEncoder; see FLAC__stream_encoder_set_verify()
*
* \default \c false
*/
static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, FLAC__bool analysis_mode, analysis_options aopts, FLAC__uint64 skip, const char *infilename, const char *outfilename);
static void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred);
-static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, const char *infilename);
+static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, decode_options_t decode_options, const char *infilename);
static FLAC__bool DecoderSession_process(DecoderSession *d);
static int DecoderSession_finish_ok(DecoderSession *d);
static int DecoderSession_finish_error(DecoderSession *d);
)
return 1;
- if(!DecoderSession_init_decoder(&decoder_session, infilename))
+ if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename))
return DecoderSession_finish_error(&decoder_session);
if(!DecoderSession_process(&decoder_session))
)
return 1;
- if(!DecoderSession_init_decoder(&decoder_session, infilename))
+ if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename))
return DecoderSession_finish_error(&decoder_session);
if(!DecoderSession_process(&decoder_session))
#endif
}
-FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, const char *infilename)
+FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, decode_options_t decode_options, const char *infilename)
{
FLAC__uint32 test = 1;
return false;
}
+ if(!decode_options.use_first_serial_number)
+ OggFLAC__stream_decoder_set_serial_number(decoder_session->decoder.ogg.stream, decode_options.serial_number);
+
OggFLAC__stream_decoder_set_read_callback(decoder_session->decoder.ogg.stream, read_callback);
/*
* The three ugly casts here are to 'downcast' the 'void *' argument of
}
}
else
+#else
+ (void)decode_options;
#endif
{
decoder_session->decoder.flac.file = FLAC__file_decoder_new();
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
if(bps != decoder_session->bps) {
- fprintf("ERROR, bits-per-sample is %u in frame but %u in STREAMINFO\n", bps, decoder_session->bps);
+ fprintf(stderr, "ERROR, bits-per-sample is %u in frame but %u in STREAMINFO\n", bps, decoder_session->bps);
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if(channels != decoder_session->channels) {
- fprintf("ERROR, channels is %u in frame but %u in STREAMINFO\n", channels, decoder_session->channels);
+ fprintf(stderr, "ERROR, channels is %u in frame but %u in STREAMINFO\n", channels, decoder_session->channels);
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
if(frame->header.sample_rate != decoder_session->sample_rate) {
- fprintf("ERROR, sample rate is %u in frame but %u in STREAMINFO\n", frame->header.sample_rate, decoder_session->sample_rate);
+ fprintf(stderr, "ERROR, sample rate is %u in frame but %u in STREAMINFO\n", frame->header.sample_rate, decoder_session->sample_rate);
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
FLAC__bool continue_through_decode_errors;
#ifdef FLAC__HAS_OGG
FLAC__bool is_ogg;
+ FLAC__bool use_first_serial_number;
+ long serial_number;
#endif
FLAC__uint64 skip;
} decode_options_t;
#ifdef FLAC__HAS_OGG
if(e->use_ogg) {
+ if(options.has_serial_number)
+ OggFLAC__stream_encoder_set_serial_number(e->encoder.ogg.stream, options.serial_number);
OggFLAC__stream_encoder_set_verify(e->encoder.ogg.stream, options.verify);
OggFLAC__stream_encoder_set_streamable_subset(e->encoder.ogg.stream, !options.lax);
OggFLAC__stream_encoder_set_do_mid_side_stereo(e->encoder.ogg.stream, options.do_mid_side);
FLAC__bool verify;
#ifdef FLAC__HAS_OGG
FLAC__bool use_ogg;
+ FLAC__bool has_serial_number;
+ long serial_number;
#endif
FLAC__bool lax;
FLAC__bool do_mid_side;
{ "padding", 1, 0, 'P' },
#ifdef FLAC__HAS_OGG
{ "ogg", 0, 0, 0 },
+ { "serial-number", 1, 0, 0 },
#endif
{ "blocksize", 1, 0, 'b' },
{ "exhaustive-model-search", 0, 0, 'e' },
FLAC__bool test_only;
FLAC__bool analyze;
FLAC__bool use_ogg;
+ FLAC__bool has_serial_number; /* true iff --serial-number was used */
+ long serial_number; /* this is the Ogg serial number and is unused for native FLAC */
FLAC__bool do_mid_side;
FLAC__bool loose_mid_side;
FLAC__bool do_exhaustive_model_search;
"%s -P%s -b %u%s -l %u%s%s%s -q %u -r %u,%u%s\n",
option_values.delete_input?" --delete-input-file":"",
option_values.sector_align?" --sector-align":"",
-#ifdef FLAC__HAS_OGG
option_values.use_ogg?" --ogg":"",
-#endif
option_values.lax?" --lax":"",
padopt,
(unsigned)option_values.blocksize,
option_values.test_only = false;
option_values.analyze = false;
option_values.use_ogg = false;
+ option_values.has_serial_number = false;
+ option_values.serial_number = 0;
option_values.do_mid_side = true;
option_values.loose_mid_side = false;
option_values.do_exhaustive_model_search = false;
else if(0 == strcmp(long_option, "ogg")) {
option_values.use_ogg = true;
}
+ else if(0 == strcmp(long_option, "serial-number")) {
+ option_values.has_serial_number = true;
+ option_values.serial_number = atol(option_argument);
+ }
#endif
else if(0 == strcmp(long_option, "endian")) {
FLAC__ASSERT(0 != option_argument);
printf(" -V, --verify Verify a correct encoding\n");
#ifdef FLAC__HAS_OGG
printf(" --ogg Use Ogg as transport layer\n");
+ printf(" --serial-number Serial number to use for the FLAC stream\n");
#endif
printf(" --lax Allow encoder to generate non-Subset files\n");
printf(" --sector-align Align multiple files on sector boundaries\n");
printf(" Ogg-FLAC. This is useful when piping input\n");
printf(" from stdin or when the filename does not end in\n");
printf(" '.ogg'.\n");
+ printf(" --serial-number Serial number to use for the FLAC stream. When\n");
+ printf(" encoding and no serial number is given, flac\n");
+ printf(" uses '0'. When decoding and no number is\n");
+ printf(" given, flac uses the serial number of the first\n");
+ printf(" page.\n");
#endif
printf(" --lax Allow encoder to generate non-Subset files\n");
printf(" --sector-align Align encoding of multiple CD format WAVE files\n");
common_options.verify = option_values.verify;
#ifdef FLAC__HAS_OGG
common_options.use_ogg = option_values.use_ogg;
+ common_options.has_serial_number = option_values.has_serial_number;
+ common_options.serial_number = option_values.serial_number;
#endif
common_options.lax = option_values.lax;
common_options.do_mid_side = option_values.do_mid_side;
common_options.continue_through_decode_errors = option_values.continue_through_decode_errors;
#ifdef FLAC__HAS_OGG
common_options.is_ogg = treat_as_ogg;
+ common_options.use_first_serial_number = !option_values.has_serial_number;
+ common_options.serial_number = option_values.serial_number;
#endif
common_options.skip = option_values.skip;
return 0 != decoder_;
}
+ bool Stream::set_serial_number(long value)
+ {
+ FLAC__ASSERT(is_valid());
+ return (bool)::OggFLAC__stream_decoder_set_serial_number(decoder_, value);
+ }
+
bool Stream::set_metadata_respond(::FLAC__MetadataType type)
{
FLAC__ASSERT(is_valid());
return 0 != encoder_;
}
+ bool Stream::set_serial_number(long value)
+ {
+ FLAC__ASSERT(is_valid());
+ return (bool)::OggFLAC__stream_encoder_set_serial_number(encoder_, value);
+ }
+
bool Stream::set_verify(bool value)
{
FLAC__ASSERT(is_valid());
typedef struct OggFLAC__StreamDecoderProtected {
OggFLAC__StreamDecoderState state;
+ FLAC__bool use_first_serial_number;
+ long serial_number;
} OggFLAC__StreamDecoderProtected;
#endif
typedef struct OggFLAC__StreamEncoderProtected {
OggFLAC__StreamEncoderState state;
+ long serial_number;
} OggFLAC__StreamEncoderProtected;
#endif
struct {
ogg_stream_state stream_state;
ogg_sync_state sync_state;
+ FLAC__bool need_serial_number;
} ogg;
} OggFLAC__StreamDecoderPrivate;
if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
return decoder->protected_->state = OggFLAC__STREAM_DECODER_INVALID_CALLBACK;
- if(ogg_stream_init(&decoder->private_->ogg.stream_state, 0) != 0)
+ decoder->private_->ogg.need_serial_number = decoder->protected_->use_first_serial_number;
+ /* we will determine the serial number later if necessary */
+ if(ogg_stream_init(&decoder->private_->ogg.stream_state, decoder->protected_->serial_number) != 0)
return decoder->protected_->state = OggFLAC__STREAM_DECODER_OGG_ERROR;
if(ogg_sync_init(&decoder->private_->ogg.sync_state) != 0)
return true;
}
+FLAC__bool OggFLAC__stream_decoder_set_serial_number(OggFLAC__StreamDecoder *decoder, long value)
+{
+ FLAC__ASSERT(0 != decoder);
+ FLAC__ASSERT(0 != decoder->private_);
+ FLAC__ASSERT(0 != decoder->protected_);
+ if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
+ return false;
+ decoder->protected_->use_first_serial_number = false;
+ decoder->protected_->serial_number = value;
+ return true;
+}
+
FLAC__bool OggFLAC__stream_decoder_set_metadata_respond(OggFLAC__StreamDecoder *decoder, FLAC__MetadataType type)
{
FLAC__ASSERT(0 != decoder);
decoder->private_->metadata_callback = 0;
decoder->private_->error_callback = 0;
decoder->private_->client_data = 0;
+ decoder->protected_->use_first_serial_number = true;
}
FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *unused, FLAC__byte buffer[], unsigned *bytes, void *client_data)
*bytes = 0;
while(ogg_sync_pageout(&decoder->private_->ogg.sync_state, &page) == 1) {
+ /* grab the serial number if necessary */
+ if(decoder->private_->ogg.need_serial_number) {
+ decoder->private_->ogg.stream_state.serialno = decoder->protected_->serial_number = ogg_page_serialno(&page);
+ decoder->private_->ogg.need_serial_number = false;
+ }
if(ogg_stream_pagein(&decoder->private_->ogg.stream_state, &page) == 0) {
ogg_packet packet;
if(0 == encoder->private_->write_callback)
return encoder->protected_->state = OggFLAC__STREAM_ENCODER_INVALID_CALLBACK;
- if(ogg_stream_init(&encoder->private_->ogg.stream_state, /*@@@serialno=*/0) != 0)
+ if(ogg_stream_init(&encoder->private_->ogg.stream_state, encoder->protected_->serial_number) != 0)
return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
FLAC__stream_encoder_set_write_callback(encoder->private_->FLAC_stream_encoder, write_callback_);
encoder->protected_->state = OggFLAC__STREAM_ENCODER_UNINITIALIZED;
}
+FLAC__bool OggFLAC__stream_encoder_set_serial_number(OggFLAC__StreamEncoder *encoder, long value)
+{
+ FLAC__ASSERT(0 != encoder);
+ FLAC__ASSERT(0 != encoder->private_);
+ FLAC__ASSERT(0 != encoder->protected_);
+ FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
+ if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
+ return false;
+ encoder->protected_->serial_number = value;
+ return true;
+}
+
FLAC__bool OggFLAC__stream_encoder_set_verify(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
{
FLAC__ASSERT(0 != encoder);
encoder->private_->write_callback = 0;
encoder->private_->client_data = 0;
+ encoder->protected_->serial_number = 0;
}
FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
}
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__STREAM_DECODER_OK)
return decoder->die();
}
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");
#endif
#define min(a,b) ((a)<(b)?(a):(b))
+const long file_utils__serial_number = 12345;
+
typedef struct {
FILE *file;
} encoder_client_struct;
return false;
}
+ OggFLAC__stream_encoder_set_serial_number(encoder, file_utils__serial_number);
OggFLAC__stream_encoder_set_verify(encoder, true);
OggFLAC__stream_encoder_set_streamable_subset(encoder, true);
OggFLAC__stream_encoder_set_do_mid_side_stereo(encoder, false);
#include "FLAC/format.h"
+extern const long file_utils__serial_number;
+
FLAC__bool file_utils__change_stats(const char *filename, FLAC__bool read_only);
FLAC__bool file_utils__remove_file(const char *filename);
}
printf("OK\n");
+ printf("testing OggFLAC__stream_decoder_set_serial_number()... ");
+ if(!OggFLAC__stream_decoder_set_serial_number(decoder, file_utils__serial_number))
+ return die_s_("returned false", decoder);
+ printf("OK\n");
+
printf("testing OggFLAC__stream_decoder_set_read_callback()... ");
if(!OggFLAC__stream_decoder_set_read_callback(decoder, stream_decoder_read_callback_))
return die_s_("returned false", decoder);
}
printf("OK\n");
+ printf("testing OggFLAC__stream_encoder_set_serial_number()... ");
+ if(!OggFLAC__stream_encoder_set_serial_number(encoder, file_utils__serial_number))
+ return die_s_("returned false", encoder);
+ printf("OK\n");
+
printf("testing OggFLAC__stream_encoder_set_verify()... ");
if(!OggFLAC__stream_encoder_set_verify(encoder, true))
return die_s_("returned false", encoder);
#endif
#define min(a,b) ((a)<(b)?(a):(b))
+const long file_utils__serial_number = 12345;
+
typedef struct {
FILE *file;
} encoder_client_struct;
return false;
}
+ OggFLAC__stream_encoder_set_serial_number(encoder, file_utils__serial_number);
OggFLAC__stream_encoder_set_verify(encoder, true);
OggFLAC__stream_encoder_set_streamable_subset(encoder, true);
OggFLAC__stream_encoder_set_do_mid_side_stereo(encoder, false);
#include "FLAC/format.h"
+extern const long file_utils__serial_number;
+
FLAC__bool file_utils__change_stats(const char *filename, FLAC__bool read_only);
FLAC__bool file_utils__remove_file(const char *filename);