add vendor string to encoding
authorJosh Coalson <jcoalson@users.sourceforce.net>
Sun, 25 Aug 2002 05:27:15 +0000 (05:27 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Sun, 25 Aug 2002 05:27:15 +0000 (05:27 +0000)
include/FLAC/format.h
src/libFLAC/format.c
src/libFLAC/stream_encoder.c
src/libFLAC/stream_encoder_framing.c

index c274b59..0ac6e3b 100644 (file)
@@ -131,16 +131,22 @@ extern "C" {
 #define FLAC__VERSION_STRING VERSION
 #endif
 
+/** The vendor string inserted by the encoder into the VORBIS_COMMENT block.
+ *  This is a nulL-terminated ASCII string; when inserted into the
+ *  VORBIS_COMMENT the trailing null is stripped.
+ */
+extern const FLAC__byte *FLAC__VENDOR_STRING;
+
 /** The byte string representation of the beginning of a FLAC stream. */
-extern const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */;
+extern const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */
 
 /** The 32-bit integer big-endian representation of the beginning of
  *  a FLAC stream.
  */
-extern const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */;
+extern const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */
 
 /** The length of the FLAC signature in bits. */
-extern const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */;
+extern const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */
 
 /** The length of the FLAC signature in bytes. */
 #define FLAC__STREAM_SYNC_LENGTH (4u)
index f52c38a..cf933cf 100644 (file)
@@ -28,6 +28,7 @@
 #endif
 #define min(a,b) ((a)<(b)?(a):(b))
 
+const FLAC__byte *FLAC__VENDOR_STRING = "reference libFLAC " FLAC__VERSION_STRING " 20020823";
 const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
 const unsigned FLAC__STREAM_SYNC = 0x664C6143;
 const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */;
index d8ab93e..3eb43f5 100644 (file)
@@ -533,6 +533,7 @@ void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
 FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
 {
        unsigned i;
+       FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment;
 
        FLAC__ASSERT(0 != encoder);
 
@@ -613,13 +614,23 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
        /* validate metadata */
        if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
                return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+       metadata_has_seektable = false;
+       metadata_has_vorbis_comment = false;
        for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
                if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
                        return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
                else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
+                       if(metadata_has_seektable) /* only one is allowed */
+                               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+                       metadata_has_seektable = true;
                        if(!FLAC__format_seektable_is_legal(&encoder->protected_->metadata[i]->data.seek_table))
                                return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
                }
+               else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
+                       if(metadata_has_vorbis_comment) /* only one is allowed */
+                               return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
+                       metadata_has_vorbis_comment = true;
+               }
        }
 
        encoder->private_->input_capacity = 0;
@@ -770,7 +781,7 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
        if(encoder->protected_->verify)
                encoder->private_->verify.state_hint = ENCODER_IN_METADATA;
        encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
-       encoder->private_->metadata.is_last = (encoder->protected_->num_metadata_blocks == 0);
+       encoder->private_->metadata.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */
        encoder->private_->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
        encoder->private_->metadata.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */
        encoder->private_->metadata.data.stream_info.max_blocksize = encoder->protected_->blocksize;
@@ -802,6 +813,32 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder)
        encoder->private_->metadata.data.stream_info.total_samples = 0;
 
        /*
+        * Check to see if the supplied metadata contains a VORBIS_COMMENT;
+        * if not, we will write an empty one (FLAC__add_metadata_block()
+        * automatically supplies the vendor string).
+        */
+       if(!metadata_has_vorbis_comment) {
+               FLAC__StreamMetadata vorbis_comment;
+               vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
+               vorbis_comment.is_last = (encoder->protected_->num_metadata_blocks == 0);
+               vorbis_comment.length = 4 + 4; /* MAGIC NUMBER */
+               vorbis_comment.data.vorbis_comment.vendor_string.length = 0;
+               vorbis_comment.data.vorbis_comment.vendor_string.entry = 0;
+               vorbis_comment.data.vorbis_comment.num_comments = 0;
+               vorbis_comment.data.vorbis_comment.comments = 0;
+               if(!FLAC__bitbuffer_clear(encoder->private_->frame)) {
+                       encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
+                       return false;
+               }
+               if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame))
+                       return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
+               if(!write_bitbuffer_(encoder, 0)) {
+                       /* the above function sets the state for us in case of an error */
+                       return encoder->protected_->state;
+               }
+       }
+
+       /*
         * write the user's metadata blocks
         */
        for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
index 63b72a4..95a701d 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <stdio.h>
+#include <string.h> /* for strlen() */
 #include "private/stream_encoder_framing.h"
 #include "private/crc.h"
 #include "FLAC/assert.h"
@@ -33,6 +34,7 @@ static FLAC__bool add_residual_partitioned_rice_(FLAC__BitBuffer *bb, const FLAC
 FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitBuffer *bb)
 {
        unsigned i;
+       const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
 
        if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->is_last, FLAC__STREAM_METADATA_IS_LAST_LEN))
                return false;
@@ -40,8 +42,16 @@ FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__
        if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->type, FLAC__STREAM_METADATA_TYPE_LEN))
                return false;
 
-       FLAC__ASSERT(metadata->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
-       if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->length, FLAC__STREAM_METADATA_LENGTH_LEN))
+       /*
+        * First, for VORBIS_COMMENTs, adjust the length to reflect our vendor string
+        */
+       i = metadata->length;
+       if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
+               i -= metadata->data.vorbis_comment.vendor_string.length;
+               i += vendor_string_length;
+       }
+       FLAC__ASSERT(i < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
+       if(!FLAC__bitbuffer_write_raw_uint32(bb, i, FLAC__STREAM_METADATA_LENGTH_LEN))
                return false;
 
        switch(metadata->type) {
@@ -95,9 +105,9 @@ FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__
                        }
                        break;
                case FLAC__METADATA_TYPE_VORBIS_COMMENT:
-                       if(!FLAC__bitbuffer_write_raw_uint32_little_endian(bb, metadata->data.vorbis_comment.vendor_string.length))
+                       if(!FLAC__bitbuffer_write_raw_uint32_little_endian(bb, vendor_string_length))
                                return false;
-                       if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.vorbis_comment.vendor_string.entry, metadata->data.vorbis_comment.vendor_string.length))
+                       if(!FLAC__bitbuffer_write_byte_block(bb, FLAC__VENDOR_STRING, vendor_string_length))
                                return false;
                        if(!FLAC__bitbuffer_write_raw_uint32_little_endian(bb, metadata->data.vorbis_comment.num_comments))
                                return false;