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;
::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);
// Private and undefined so you can't use them:
Stream(const Stream &);
* \ingroup oggflac
*
* \brief
- * This module describes the encoder layers provided by libOggFLAC.
+ * This module describes the three encoder layers provided by libOggFLAC.
*
- * libOggFLAC currently provides the same stream layer access as libFLAC;
- * the interface is nearly identical. See the \link flac_encoder FLAC
+ * libOggFLAC currently provides the same three layers of access as libFLAC;
+ * the interfaces are nearly identical, with the addition of a method for
+ * specifying the Ogg serial number. See the \link flac_encoder FLAC
* encoder module \endlink for full documentation.
*/
* encoder.
*
* The interface here is nearly identical to FLAC's stream encoder,
- * including the callbacks. See the \link flac_stream_encoder
- * FLAC stream encoder module \endlink for full documentation.
+ * including the callbacks, with the addition of
+ * OggFLAC__stream_encoder_set_serial_number(). See the
+ * \link flac_stream_encoder FLAC stream encoder module \endlink
+ * for full documentation.
*
* \{
*/
*/
typedef FLAC__StreamEncoderWriteStatus (*OggFLAC__StreamEncoderWriteCallback)(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
+/** Signature for the metadata callback.
+ * See OggFLAC__stream_encoder_set_metadata_callback()
+ * and FLAC__stream_encoder_set_metadata_callback() for more info.
+ *
+ * \param encoder The encoder instance calling the callback.
+ * \param metadata The final populated STREAMINFO block.
+ * \param client_data The callee's client data set through
+ * FLAC__stream_encoder_set_client_data().
+ */
+typedef void (*OggFLAC__StreamEncoderMetadataCallback)(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
+
/***********************************************************************
*
*/
OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_write_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderWriteCallback value);
+/** Set the metadata callback.
+ * This is inherited from FLAC__StreamEncoder; see
+ * FLAC__stream_encoder_set_metadata_callback().
+ *
+ * \note
+ * The callback is mandatory and must be set before initialization.
+ *
+ * \default \c NULL
+ * \param encoder An encoder instance to set.
+ * \param value See above.
+ * \assert
+ * \code encoder != NULL \endcode
+ * \code value != NULL \endcode
+ * \retval FLAC__bool
+ * \c false if the encoder is already initialized, else \c true.
+ */
+OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderMetadataCallback value);
+
/** Set the client data to be passed back to callbacks.
* This value will be supplied to callbacks in their \a client_data
* argument.
{
FLAC__ASSERT(is_valid());
::OggFLAC__stream_encoder_set_write_callback(encoder_, write_callback_);
+ ::OggFLAC__stream_encoder_set_metadata_callback(encoder_, metadata_callback_);
::OggFLAC__stream_encoder_set_client_data(encoder_, (void*)this);
return State(::OggFLAC__stream_encoder_init(encoder_));
}
return instance->write_callback(buffer, bytes, samples, current_frame);
}
+ void Stream::metadata_callback_(const ::OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
+ {
+ (void)encoder;
+ FLAC__ASSERT(0 != client_data);
+ Stream *instance = reinterpret_cast<Stream *>(client_data);
+ FLAC__ASSERT(0 != instance);
+ return instance->metadata_callback(metadata);
+ }
+
};
};
typedef struct OggFLAC__StreamEncoderPrivate {
OggFLAC__StreamEncoderWriteCallback write_callback;
+ OggFLAC__StreamEncoderMetadataCallback metadata_callback;
void *client_data;
FLAC__StreamEncoder *FLAC_stream_encoder;
/* internal vars (all the above are class settings) */
if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
return encoder->protected_->state = OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
- if(0 == encoder->private_->write_callback)
+ if(0 == encoder->private_->write_callback || 0 == encoder->private_->metadata_callback)
return encoder->protected_->state = OggFLAC__STREAM_ENCODER_INVALID_CALLBACK;
if(ogg_stream_init(&encoder->private_->ogg.stream_state, encoder->protected_->serial_number) != 0)
return true;
}
+OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderMetadataCallback value)
+{
+ FLAC__ASSERT(0 != encoder);
+ FLAC__ASSERT(0 != encoder->private_);
+ FLAC__ASSERT(0 != encoder->protected_);
+ FLAC__ASSERT(0 != value);
+ if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
+ return false;
+ encoder->private_->metadata_callback = value;
+ return true;
+}
+
OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_client_data(OggFLAC__StreamEncoder *encoder, void *value)
{
FLAC__ASSERT(0 != encoder);
FLAC__ASSERT(0 != encoder);
encoder->private_->write_callback = 0;
+ encoder->private_->metadata_callback = 0;
encoder->private_->client_data = 0;
encoder->protected_->serial_number = 0;
}
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
-void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
+void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
{
- /*
- * We don't try to go back and update metadata blocks by mucking
- * around inside the Ogg layer. Maybe someday we will care to
- * and an OggFLAC__SeekableStreamEncoder and OggFLAC__FileEncoder
- * will be possible but it may just never be useful.
- */
- (void)encoder, (void)metadata, (void)client_data;
+ OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)client_data;
+
+ (void)unused;
+ FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
+
+ encoder->private_->metadata_callback(encoder, metadata, encoder->private_->client_data);
}
// 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);
bool die(const char *msg = 0) const;
};
return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
+void StreamEncoder::metadata_callback(const FLAC__StreamMetadata *metadata)
+{
+ (void)metadata;
+}
+
bool StreamEncoder::die(const char *msg) const
{
State state = get_state();
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
+static void stream_encoder_metadata_callback_(const OggFLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+ (void)encoder, (void)metadata, (void)client_data;
+}
+
+
static FLAC__bool test_stream_encoder()
{
OggFLAC__StreamEncoder *encoder;
return die_s_("returned false", encoder);
printf("OK\n");
+ printf("testing OggFLAC__stream_encoder_set_metadata_callback()... ");
+ if(!OggFLAC__stream_encoder_set_metadata_callback(encoder, stream_encoder_metadata_callback_))
+ return die_s_("returned false", encoder);
+ printf("OK\n");
+
printf("testing OggFLAC__stream_encoder_set_client_data()... ");
if(!OggFLAC__stream_encoder_set_client_data(encoder, 0))
return die_s_("returned false", encoder);