add support for new PICTURE metadata block
diff --git a/include/FLAC++/metadata.h b/include/FLAC++/metadata.h
index 549546b..9641f91 100644
--- a/include/FLAC++/metadata.h
+++ b/include/FLAC++/metadata.h
@@ -782,6 +782,80 @@
FLAC__uint32 calculate_cddb_id() const;
};
+ /** PICTURE metadata block.
+ * See <A HREF="../format.html#metadata_block_picture">format specification</A>.
+ */
+ class FLACPP_API Picture : public Prototype {
+ public:
+ Picture();
+
+ //@{
+ /** Constructs a copy of the given object. This form
+ * always performs a deep copy.
+ */
+ inline Picture(const Picture &object): Prototype(object) { }
+ inline Picture(const ::FLAC__StreamMetadata &object): Prototype(object) { }
+ inline Picture(const ::FLAC__StreamMetadata *object): Prototype(object) { }
+ //@}
+
+ /** Constructs an object with copy control. See
+ * Prototype(::FLAC__StreamMetadata *object, bool copy).
+ */
+ inline Picture(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
+
+ ~Picture();
+
+ //@{
+ /** Assign from another object. Always performs a deep copy. */
+ inline Picture &operator=(const Picture &object) { Prototype::operator=(object); return *this; }
+ inline Picture &operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); return *this; }
+ inline Picture &operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); return *this; }
+ //@}
+
+ /** Assigns an object with copy control. See
+ * Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy).
+ */
+ inline Picture &assign(::FLAC__StreamMetadata *object, bool copy) { Prototype::assign_object(object, copy); return *this; }
+
+ //@{
+ /** Check for equality, performing a deep compare by following pointers. */
+ inline bool operator==(const Picture &object) const { return Prototype::operator==(object); }
+ inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
+ inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
+ //@}
+
+ //@{
+ /** Check for inequality, performing a deep compare by following pointers. */
+ inline bool operator!=(const Picture &object) const { return Prototype::operator!=(object); }
+ inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
+ inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
+ //@}
+
+ ::FLAC__StreamMetadata_Picture_Type get_type() const;
+ const char *get_mime_type() const; // NUL-terminated printable ASCII string
+ const FLAC__byte *get_description() const; // NUL-terminated UTF-8 string
+ FLAC__uint32 get_width() const;
+ FLAC__uint32 get_height() const;
+ FLAC__uint32 get_depth() const;
+ FLAC__uint32 get_data_length() const;
+ const FLAC__byte *get_data() const;
+
+ void set_type(::FLAC__StreamMetadata_Picture_Type type);
+
+ //! See FLAC__metadata_object_picture_set_mime_type()
+ bool set_mime_type(const char *string); // NUL-terminated printable ASCII string
+
+ //! See FLAC__metadata_object_picture_set_description()
+ bool set_description(const FLAC__byte *string); // NUL-terminated UTF-8 string
+
+ void set_width(FLAC__uint32 value) const;
+ void set_height(FLAC__uint32 value) const;
+ void set_depth(FLAC__uint32 value) const;
+
+ //! See FLAC__metadata_object_picture_set_data()
+ bool set_data(const FLAC__byte *data, FLAC__uint32 data_length);
+ };
+
/** Opaque metadata block for storing unknown types.
* This should not be used unless you know what you are doing;
* it is currently used only internally to support forward
@@ -855,16 +929,16 @@
* \{
*/
- //! See FLAC__metadata_get_streaminfo().
- FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
+ FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo); //< See FLAC__metadata_get_streaminfo().
- //! See FLAC__metadata_get_tags().
- FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags);
- FLACPP_API bool get_tags(const char *filename, VorbisComment &tags);
+ FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags); //< See FLAC__metadata_get_tags().
+ FLACPP_API bool get_tags(const char *filename, VorbisComment &tags); //< See FLAC__metadata_get_tags().
- //! See FLAC__metadata_get_cuesheet().
- FLACPP_API bool get_cuesheet(const char *filename, CueSheet *&cuesheet);
- FLACPP_API bool get_cuesheet(const char *filename, CueSheet &cuesheet);
+ FLACPP_API bool get_cuesheet(const char *filename, CueSheet *&cuesheet); //! See FLAC__metadata_get_cuesheet().
+ FLACPP_API bool get_cuesheet(const char *filename, CueSheet &cuesheet); //! See FLAC__metadata_get_cuesheet().
+
+ FLACPP_API bool get_picture(const char *filename, Picture *&picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth); //! See FLAC__metadata_get_picture().
+ FLACPP_API bool get_picture(const char *filename, Picture &picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth); //! See FLAC__metadata_get_picture().
/* \} */
diff --git a/include/FLAC/format.h b/include/FLAC/format.h
index de9f6ea..6d09df6 100644
--- a/include/FLAC/format.h
+++ b/include/FLAC/format.h
@@ -478,7 +478,10 @@
FLAC__METADATA_TYPE_CUESHEET = 5,
/**< <A HREF="../format.html#metadata_block_cuesheet">CUESHEET</A> block */
- FLAC__METADATA_TYPE_UNDEFINED = 6
+ FLAC__METADATA_TYPE_PICTURE = 6,
+ /**< <A HREF="../format.html#metadata_block_picture">PICTURE</A> block */
+
+ FLAC__METADATA_TYPE_UNDEFINED = 7
/**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */
} FLAC__MetadataType;
@@ -678,7 +681,7 @@
/**< The number of lead-in samples. */
FLAC__bool is_cd;
- /**< \c true if CUESHEET corresponds to a Compact Disc, else \c false */
+ /**< \c true if CUESHEET corresponds to a Compact Disc, else \c false. */
unsigned num_tracks;
/**< The number of tracks. */
@@ -695,6 +698,92 @@
extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */
+/** An enumeration of the PICTURE types (see FLAC__StreamMetadataPicture and id3 v2.4 APIC tag). */
+typedef enum {
+ FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER = 0, /**< Other */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD = 1, /**< 32x32 pixels 'file icon' (PNG only) */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON = 2, /**< Other file icon */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER = 3, /**< Cover (front) */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_BACK_COVER = 4, /**< Cover (back) */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEAFLET_PAGE = 5, /**< Leaflet page */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA = 6, /**< Media (e.g. label side of CD) */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEAD_ARTIST = 7, /**< Lead artist/lead performer/soloist */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_ARTIST = 8, /**< Artist/performer */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_CONDUCTOR = 9, /**< Conductor */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_BAND = 10, /**< Band/Orchestra */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_COMPOSER = 11, /**< Composer */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LYRICIST = 12, /**< Lyricist/text writer */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_RECORDING_LOCATION = 13, /**< Recording Location */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_RECORDING = 14, /**< During recording */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_PERFORMANCE = 15, /**< During performance */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_VIDEO_SCREEN_CAPTURE = 16, /**< Movie/video screen capture */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_FISH = 17, /**< A bright coloured fish */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_ILLUSTRATION = 18, /**< Illustration */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_BAND_LOGOTYPE = 19, /**< Band/artist logotype */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_PUBLISHER_LOGOTYPE = 20, /**< Publisher/Studio logotype */
+ FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED
+} FLAC__StreamMetadata_Picture_Type;
+
+/** Maps a FLAC__StreamMetadata_Picture_Type to a C string.
+ *
+ * Using a FLAC__StreamMetadata_Picture_Type as the index to this array
+ * will give the string equivalent. The contents should not be
+ * modified.
+ */
+extern FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[];
+
+/** FLAC PICTURE structure. (See the
+ * <A HREF="../format.html#metadata_block_picture">format specification</A>
+ * for the full description of each field.)
+ */
+typedef struct {
+ FLAC__StreamMetadata_Picture_Type type;
+ /**< The kind of picture stored. */
+
+ char *mime_type;
+ /**< Picture data's MIME type, in ASCII printable characters
+ * 0x20-0x7e, NUL terminated. For best compatibility with players,
+ * use picture data of MIME type \c image/jpeg or \c image/png. A
+ * MIME type of '-->' is also allowed, in which case the picture
+ * data should be a complete URL. In file storage, the MIME type is
+ * stored as a 32-bit length followed by the ASCII string with no NUL
+ * terminator, but is converted to a plain C string in this structure
+ * for convenience.
+ */
+
+ FLAC__byte *description;
+ /**< Picture's description in UTF-8, NUL terminated. In file storage,
+ * the description is stored as a 32-bit length followed by the UTF-8
+ * string with no NUL terminator, but is converted to a plain C string
+ * in this structure for convenience.
+ */
+
+ FLAC__uint32 width;
+ /**< Picture's width in pixels. */
+
+ FLAC__uint32 height;
+ /**< Picture's height in pixels. */
+
+ FLAC__uint32 depth;
+ /**< Picture's color depth in bits-per-pixel. */
+
+ FLAC__uint32 data_length;
+ /**< Length of binary picture data in bytes. */
+
+ FLAC__byte *data;
+ /**< Binary picture data. */
+
+} FLAC__StreamMetadata_Picture;
+
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN; /**< == 32 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN; /**< == 32 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN; /**< == 32 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN; /**< == 32 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN; /**< == 32 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN; /**< == 32 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN; /**< == 32 (bits) */
+
+
/** Structure that is used when a metadata block of unknown type is loaded.
* The contents are opaque. The structure is used only internally to
* correctly handle unknown metadata.
@@ -725,6 +814,7 @@
FLAC__StreamMetadata_SeekTable seek_table;
FLAC__StreamMetadata_VorbisComment vorbis_comment;
FLAC__StreamMetadata_CueSheet cue_sheet;
+ FLAC__StreamMetadata_Picture picture;
FLAC__StreamMetadata_Unknown unknown;
} data;
/**< Polymorphic block data; use the \a type value to determine which
@@ -852,6 +942,25 @@
*/
FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation);
+/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
+/** Check picture data to see if it conforms to the FLAC specification.
+ * See the format specification for limits on the contents of the
+ * PICTURE block.
+ *
+ * \param picture A pointer to existing picture data to be checked.
+ * \param violation Address of a pointer to a string. If there is a
+ * violation, a pointer to a string explanation of the
+ * violation will be returned here. \a violation may be
+ * \c NULL if you don't need the returned string. Do not
+ * free the returned string; it will always point to static
+ * data.
+ * \assert
+ * \code picture != NULL \endcode
+ * \retval FLAC__bool
+ * \c false if picture data is illegal, else \c true.
+ */
+FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation);
+
/* \} */
#ifdef __cplusplus
diff --git a/include/FLAC/metadata.h b/include/FLAC/metadata.h
index e5799de..68b2453 100644
--- a/include/FLAC/metadata.h
+++ b/include/FLAC/metadata.h
@@ -64,7 +64,8 @@
* There are three metadata interfaces of increasing complexity:
*
* Level 0:
- * Read-only access to the STREAMINFO and VORBIS_COMMENT blocks.
+ * Read-only access to the STREAMINFO, VORBIS_COMMENT, CUESHEET, and
+ * PICTURE blocks.
*
* Level 1:
* Read-write access to all metadata blocks. This level is write-
@@ -124,7 +125,8 @@
*
* \brief
* The level 0 interface consists of individual routines to read the
- * STREAMINFO, VORBIS_COMMENT, and CUESHEET blocks, requiring only a filename.
+ * STREAMINFO, VORBIS_COMMENT, CUESHEET, and PICTURE blocks, requiring
+ * only a filename.
*
* They try to skip any ID3v2 tag at the head of the file.
*
@@ -162,7 +164,7 @@
* \code tags != NULL \endcode
* \retval FLAC__bool
* \c true if a valid VORBIS_COMMENT block was read from \a filename,
- * and \a *tags will be set to the address of the tag structure.
+ * and \a *tags will be set to the address of the metadata structure.
* Returns \c false if there was a memory allocation error, a file
* decoder error, or the file contained no VORBIS_COMMENT block, and
* \a *tags will be set to \c NULL.
@@ -181,13 +183,51 @@
* \code cuesheet != NULL \endcode
* \retval FLAC__bool
* \c true if a valid CUESHEET block was read from \a filename,
- * and \a *cuesheet will be set to the address of the tag structure.
- * Returns \c false if there was a memory allocation error, a file
- * decoder error, or the file contained no CUESHEET block, and
- * \a *cuesheet will be set to \c NULL.
+ * and \a *cuesheet will be set to the address of the metadata
+ * structure. Returns \c false if there was a memory allocation
+ * error, a file decoder error, or the file contained no CUESHEET
+ * block, and \a *cuesheet will be set to \c NULL.
*/
FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet);
+/** Read a PICTURE metadata block of the given FLAC file. This
+ * function will try to skip any ID3v2 tag at the head of the file.
+ * Since there can be more than one PICTURE block in a file, this
+ * function takes a number of parameters that act as constraints to
+ * the search. The PICTURE block with the largest area matching all
+ * the constraints will be returned, or \a *picture will be set to
+ * \c NULL if there was no such block.
+ *
+ * \param filename The path to the FLAC file to read.
+ * \param picture The address where the returned pointer will be
+ * stored. The \a picture object must be deleted by
+ * the caller using FLAC__metadata_object_delete().
+ * \param type The desired picture type. Use \c -1 to mean
+ * "any type".
+ * \param mime_type The desired MIME type, e.g. "image/jpeg". The
+ * string will be matched exactly. Use \c NULL to
+ * mean "any MIME type".
+ * \param description The desired description. The string will be
+ * matched exactly. Use \c NULL to mean "any
+ * description".
+ * \param max_width The maximum width in pixels desired. Use
+ * \c (unsigned)(-1) to mean "any width".
+ * \param max_height The maximum height in pixels desired. Use
+ * \c (unsigned)(-1) to mean "any height".
+ * \param max_depth The maximum color depth in bits-per-pixel desired.
+ * Use \c (unsigned)(-1) to mean "any depth".
+ * \assert
+ * \code filename != NULL \endcode
+ * \code picture != NULL \endcode
+ * \retval FLAC__bool
+ * \c true if a valid PICTURE block was read from \a filename,
+ * and \a *picture will be set to the address of the metadata
+ * structure. Returns \c false if there was a memory allocation
+ * error, a file decoder error, or the file contained no PICTURE
+ * block, and \a *picture will be set to \c NULL.
+ */
+FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth);
+
/* \} */
@@ -203,9 +243,9 @@
* - Create an iterator using FLAC__metadata_simple_iterator_new()
* - Attach it to a file using FLAC__metadata_simple_iterator_init() and check
* the exit code. Call FLAC__metadata_simple_iterator_is_writable() to
- * see if the file is writable, or read-only access is allowed.
+ * see if the file is writable, or only read access is allowed.
* - Use FLAC__metadata_simple_iterator_next() and
- * FLAC__metadata_simple_iterator_prev() to move around the blocks.
+ * FLAC__metadata_simple_iterator_prev() to traverse the blocks.
* This is does not read the actual blocks themselves.
* FLAC__metadata_simple_iterator_next() is relatively fast.
* FLAC__metadata_simple_iterator_prev() is slower since it needs to search
@@ -1185,7 +1225,11 @@
/** Sets the application data of an APPLICATION block.
*
* If \a copy is \c true, a copy of the data is stored; otherwise, the object
- * takes ownership of the pointer.
+ * takes ownership of the pointer. The existing data will be freed if this
+ * function is successful, otherwise the original data will remain if \a copy
+ * is \c true and malloc() fails.
+ *
+ * \note It is safe to pass a const pointer to \a data if \a copy is \c true.
*
* \param object A pointer to an existing APPLICATION object.
* \param data A pointer to the data to set.
@@ -1911,6 +1955,95 @@
*/
FLAC_API FLAC__uint32 FLAC__metadata_object_cuesheet_calculate_cddb_id(const FLAC__StreamMetadata *object);
+/** Sets the MIME type of a PICTURE block.
+ *
+ * If \a copy is \c true, a copy of the string is stored; otherwise, the object
+ * takes ownership of the pointer. The existing string will be freed if this
+ * function is successful, otherwise the original string will remain if \a copy
+ * is \c true and malloc() fails.
+ *
+ * \note It is safe to pass a const pointer to \a mime_type if \a copy is \c true.
+ *
+ * \param object A pointer to an existing PICTURE object.
+ * \param mime_type A pointer to the MIME type string. The string must be
+ * ASCII characters 0x20-0x7e, NUL-terminated. No validation
+ * is done.
+ * \param copy See above.
+ * \assert
+ * \code object != NULL \endcode
+ * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode
+ * \code (mime_type != NULL) \endcode
+ * \retval FLAC__bool
+ * \c false if \a copy is \c true and malloc() fails, else \c true.
+ */
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy);
+
+/** Sets the description of a PICTURE block.
+ *
+ * If \a copy is \c true, a copy of the string is stored; otherwise, the object
+ * takes ownership of the pointer. The existing string will be freed if this
+ * function is successful, otherwise the original string will remain if \a copy
+ * is \c true and malloc() fails.
+ *
+ * \note It is safe to pass a const pointer to \a description if \a copy is \c true.
+ *
+ * \param object A pointer to an existing PICTURE object.
+ * \param description A pointer to the description string. The string must be
+ * valid UTF-8, NUL-terminated. No validation is done.
+ * \param copy See above.
+ * \assert
+ * \code object != NULL \endcode
+ * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode
+ * \code (description != NULL) \endcode
+ * \retval FLAC__bool
+ * \c false if \a copy is \c true and malloc() fails, else \c true.
+ */
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy);
+
+/** Sets the picture data of a PICTURE block.
+ *
+ * If \a copy is \c true, a copy of the data is stored; otherwise, the object
+ * takes ownership of the pointer. Also sets the \a data_length field of the
+ * metadata object to what is passed in as the \a length parameter. The
+ * existing data will be freed if this function is successful, otherwise the
+ * original data and data_length will remain if \a copy is \c true and
+ * malloc() fails.
+ *
+ * \note It is safe to pass a const pointer to \a data if \a copy is \c true.
+ *
+ * \param object A pointer to an existing PICTURE object.
+ * \param data A pointer to the data to set.
+ * \param length The length of \a data in bytes.
+ * \param copy See above.
+ * \assert
+ * \code object != NULL \endcode
+ * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode
+ * \code (data != NULL && length > 0) ||
+ * (data == NULL && length == 0 && copy == false) \endcode
+ * \retval FLAC__bool
+ * \c false if \a copy is \c true and malloc() fails, else \c true.
+ */
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy);
+
+/** Check a PICTURE block to see if it conforms to the FLAC specification.
+ * See the format specification for limits on the contents of the
+ * PICTURE block.
+ *
+ * \param picture A pointer to existing PICTURE block to be checked.
+ * \param violation Address of a pointer to a string. If there is a
+ * violation, a pointer to a string explanation of the
+ * violation will be returned here. \a violation may be
+ * \c NULL if you don't need the returned string. Do not
+ * free the returned string; it will always point to static
+ * data.
+ * \assert
+ * \code object != NULL \endcode
+ * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode
+ * \retval FLAC__bool
+ * \c false if PICTURE block is illegal, else \c true.
+ */
+FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation);
+
/* \} */
#ifdef __cplusplus
diff --git a/include/test_libs_common/metadata_utils.h b/include/test_libs_common/metadata_utils.h
index 3d7af19..882bf5b 100644
--- a/include/test_libs_common/metadata_utils.h
+++ b/include/test_libs_common/metadata_utils.h
@@ -40,6 +40,8 @@
FLAC__bool mutils__compare_block_data_cuesheet(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy);
+FLAC__bool mutils__compare_block_data_picture(const FLAC__StreamMetadata_Picture *block, const FLAC__StreamMetadata_Picture *blockcopy);
+
FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length);
FLAC__bool mutils__compare_block(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy);
@@ -52,6 +54,7 @@
FLAC__StreamMetadata *application2,
FLAC__StreamMetadata *vorbiscomment,
FLAC__StreamMetadata *cuesheet,
+ FLAC__StreamMetadata *picture,
FLAC__StreamMetadata *unknown
);
@@ -63,6 +66,7 @@
FLAC__StreamMetadata *application2,
FLAC__StreamMetadata *vorbiscomment,
FLAC__StreamMetadata *cuesheet,
+ FLAC__StreamMetadata *picture,
FLAC__StreamMetadata *unknown
);
diff --git a/src/libFLAC++/metadata.cpp b/src/libFLAC++/metadata.cpp
index fc55703..30ca841 100644
--- a/src/libFLAC++/metadata.cpp
+++ b/src/libFLAC++/metadata.cpp
@@ -68,6 +68,9 @@
case FLAC__METADATA_TYPE_CUESHEET:
ret = new CueSheet(object, /*copy=*/false);
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ ret = new Picture(object, /*copy=*/false);
+ break;
default:
ret = new Unknown(object, /*copy=*/false);
break;
@@ -87,6 +90,7 @@
const SeekTable *seektable = dynamic_cast<const SeekTable *>(object);
const VorbisComment *vorbiscomment = dynamic_cast<const VorbisComment *>(object);
const CueSheet *cuesheet = dynamic_cast<const CueSheet *>(object);
+ const Picture *picture = dynamic_cast<const Picture *>(object);
const Unknown *unknown = dynamic_cast<const Unknown *>(object);
if(0 != streaminfo)
@@ -101,6 +105,8 @@
return new VorbisComment(*vorbiscomment);
else if(0 != cuesheet)
return new CueSheet(*cuesheet);
+ else if(0 != picture)
+ return new Picture(*picture);
else if(0 != unknown)
return new Unknown(*unknown);
else {
@@ -1015,6 +1021,111 @@
//
+ // Picture
+ //
+
+ Picture::Picture():
+ Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE), /*copy=*/false)
+ { }
+
+ Picture::~Picture()
+ { }
+
+ ::FLAC__StreamMetadata_Picture_Type Picture::get_type() const
+ {
+ FLAC__ASSERT(is_valid());
+ return object_->data.picture.type;
+ }
+
+ const char *Picture::get_mime_type() const
+ {
+ FLAC__ASSERT(is_valid());
+ return object_->data.picture.mime_type;
+ }
+
+ const FLAC__byte *Picture::get_description() const
+ {
+ FLAC__ASSERT(is_valid());
+ return object_->data.picture.description;
+ }
+
+ FLAC__uint32 Picture::get_width() const
+ {
+ FLAC__ASSERT(is_valid());
+ return object_->data.picture.width;
+ }
+
+ FLAC__uint32 Picture::get_height() const
+ {
+ FLAC__ASSERT(is_valid());
+ return object_->data.picture.height;
+ }
+
+ FLAC__uint32 Picture::get_depth() const
+ {
+ FLAC__ASSERT(is_valid());
+ return object_->data.picture.depth;
+ }
+
+ FLAC__uint32 Picture::get_data_length() const
+ {
+ FLAC__ASSERT(is_valid());
+ return object_->data.picture.data_length;
+ }
+
+ const FLAC__byte *Picture::get_data() const
+ {
+ FLAC__ASSERT(is_valid());
+ return object_->data.picture.data;
+ }
+
+ void Picture::set_type(::FLAC__StreamMetadata_Picture_Type type)
+ {
+ FLAC__ASSERT(is_valid());
+ object_->data.picture.type = type;
+ }
+
+ bool Picture::set_mime_type(const char *string)
+ {
+ FLAC__ASSERT(is_valid());
+ // We can safely const_cast since copy=true
+ return (bool)::FLAC__metadata_object_picture_set_mime_type(object_, const_cast<char*>(string), /*copy=*/true);
+ }
+
+ bool Picture::set_description(const FLAC__byte *string)
+ {
+ FLAC__ASSERT(is_valid());
+ // We can safely const_cast since copy=true
+ return (bool)::FLAC__metadata_object_picture_set_description(object_, const_cast<FLAC__byte*>(string), /*copy=*/true);
+ }
+
+ void Picture::set_width(FLAC__uint32 value) const
+ {
+ FLAC__ASSERT(is_valid());
+ object_->data.picture.width = value;
+ }
+
+ void Picture::set_height(FLAC__uint32 value) const
+ {
+ FLAC__ASSERT(is_valid());
+ object_->data.picture.height = value;
+ }
+
+ void Picture::set_depth(FLAC__uint32 value) const
+ {
+ FLAC__ASSERT(is_valid());
+ object_->data.picture.depth = value;
+ }
+
+ bool Picture::set_data(const FLAC__byte *data, FLAC__uint32 data_length)
+ {
+ FLAC__ASSERT(is_valid());
+ // We can safely const_cast since copy=true
+ return (bool)::FLAC__metadata_object_picture_set_data(object_, const_cast<FLAC__byte*>(data), data_length, /*copy=*/true);
+ }
+
+
+ //
// Unknown
//
@@ -1124,6 +1235,36 @@
return false;
}
+ FLACPP_API bool get_picture(const char *filename, Picture *&picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth)
+ {
+ FLAC__ASSERT(0 != filename);
+
+ ::FLAC__StreamMetadata *object;
+
+ picture = 0;
+
+ if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth)) {
+ picture = new Picture(object, /*copy=*/false);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ FLACPP_API bool get_picture(const char *filename, Picture &picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth)
+ {
+ FLAC__ASSERT(0 != filename);
+
+ ::FLAC__StreamMetadata *object;
+
+ if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth)) {
+ picture.assign(object, /*copy=*/false);
+ return true;
+ }
+ else
+ return false;
+ }
+
// ============================================================
//
diff --git a/src/libFLAC/format.c b/src/libFLAC/format.c
index 939ec67..bb5feeb 100644
--- a/src/libFLAC/format.c
+++ b/src/libFLAC/format.c
@@ -104,6 +104,14 @@
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
+
FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
@@ -168,7 +176,32 @@
"APPLICATION",
"SEEKTABLE",
"VORBIS_COMMENT",
- "CUESHEET"
+ "CUESHEET",
+ "PICTURE"
+};
+
+FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[] = {
+ "Other",
+ "32x32 pixels 'file icon' (PNG only)",
+ "Other file icon",
+ "Cover (front)",
+ "Cover (back)",
+ "Leaflet page",
+ "Media (e.g. label side of CD)",
+ "Lead artist/lead performer/soloist",
+ "Artist/performer",
+ "Conductor",
+ "Band/Orchestra",
+ "Composer",
+ "Lyricist/text writer",
+ "Recording Location",
+ "During recording",
+ "During performance",
+ "Movie/video screen capture",
+ "A bright coloured fish",
+ "Illustration",
+ "Band/artist logotype",
+ "Publisher/Studio logotype"
};
FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate)
@@ -437,6 +470,30 @@
return true;
}
+FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation)
+{
+ char *p;
+ FLAC__byte *b;
+
+ for(p = picture->mime_type; *p; p++) {
+ if(*p < 0x20 || *p > 0x7e) {
+ if(violation) *violation = "MIME type string must contain only printable ASCII characters (0x20-0x7e)";
+ return false;
+ }
+ }
+
+ for(b = picture->description; *b; ) {
+ unsigned n = utf8len_(b);
+ if(n == 0) {
+ if(violation) *violation = "description string must be valid UTF-8";
+ return false;
+ }
+ b += n;
+ }
+
+ return true;
+}
+
/*
* These routines are private to libFLAC
*/
diff --git a/src/libFLAC/include/private/metadata.h b/src/libFLAC/include/private/metadata.h
index 277d989..7d4b5d8 100644
--- a/src/libFLAC/include/private/metadata.h
+++ b/src/libFLAC/include/private/metadata.h
@@ -34,7 +34,12 @@
#include "FLAC/metadata.h"
+/* WATCHOUT: all malloc()ed data in the block is free()ed; this may not
+ * be a consistent state (e.g. PICTURE) or equivalent to the initial
+ * state after FLAC__metadata_object_new()
+ */
void FLAC__metadata_object_delete_data(FLAC__StreamMetadata *object);
+
void FLAC__metadata_object_cuesheet_track_delete_data(FLAC__StreamMetadata_CueSheet_Track *object);
#endif
diff --git a/src/libFLAC/metadata_iterators.c b/src/libFLAC/metadata_iterators.c
index 2ecb8b1..a1c699a 100644
--- a/src/libFLAC/metadata_iterators.c
+++ b/src/libFLAC/metadata_iterators.c
@@ -92,6 +92,7 @@
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block);
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track);
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block);
+static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block);
static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length);
static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
@@ -104,6 +105,7 @@
static FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block);
static FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block);
static FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block);
+static FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block);
static FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length);
static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block);
@@ -274,6 +276,55 @@
cd->got_error = true;
}
+FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth)
+{
+ FLAC__Metadata_SimpleIterator *it;
+ FLAC__uint64 max_area_seen = 0;
+ FLAC__uint64 max_depth_seen = 0;
+
+ FLAC__ASSERT(0 != filename);
+ FLAC__ASSERT(0 != picture);
+
+ *picture = 0;
+
+ it = FLAC__metadata_simple_iterator_new();
+ if(0 == it)
+ return false;
+ if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
+ FLAC__metadata_simple_iterator_delete(it);
+ return false;
+ }
+ do {
+ if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) {
+ FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it);
+ FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height;
+ /* check constraints */
+ if(
+ (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) &&
+ (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) &&
+ (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) &&
+ obj->data.picture.width <= max_width &&
+ obj->data.picture.height <= max_height &&
+ obj->data.picture.depth <= max_depth &&
+ (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen))
+ ) {
+ if(*picture)
+ FLAC__metadata_object_delete(*picture);
+ *picture = obj;
+ max_area_seen = area;
+ max_depth_seen = obj->data.picture.depth;
+ }
+ else {
+ FLAC__metadata_object_delete(obj);
+ }
+ }
+ } while(FLAC__metadata_simple_iterator_next(it));
+
+ FLAC__metadata_simple_iterator_delete(it);
+
+ return (0 != *picture);
+}
+
/****************************************************************************
*
@@ -1851,6 +1902,8 @@
return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment);
case FLAC__METADATA_TYPE_CUESHEET:
return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet);
+ case FLAC__METADATA_TYPE_PICTURE:
+ return read_metadata_block_data_picture_cb_(handle, read_cb, &block->data.picture);
default:
return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length);
}
@@ -1882,7 +1935,6 @@
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
-
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length)
{
(void)block; /* nothing to do; we don't care about reading the padding bytes */
@@ -1947,7 +1999,7 @@
const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
FLAC__byte buffer[4]; /* magic number is asserted below */
- FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == 4);
+ FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == sizeof(buffer));
if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
@@ -1979,7 +2031,7 @@
const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
FLAC__byte buffer[4]; /* magic number is asserted below */
- FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == 4);
+ FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == sizeof(buffer));
if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string))))
return status;
@@ -2117,6 +2169,85 @@
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
+FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cstring_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__byte **data, FLAC__uint32 *length, FLAC__uint32 length_len)
+{
+ FLAC__byte buffer[sizeof(FLAC__uint32)];
+
+ FLAC__ASSERT(0 != data);
+ FLAC__ASSERT(length_len%8 == 0);
+
+ length_len /= 8; /* convert to bytes */
+
+ FLAC__ASSERT(sizeof(buffer) >= length_len);
+
+ if(read_cb(buffer, 1, length_len, handle) != length_len)
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+ *length = unpack_uint32_(buffer, length_len);
+
+ if(0 != *data)
+ free(*data);
+
+ if(0 == (*data = (FLAC__byte*)malloc(*length+1)))
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
+
+ if(*length > 0) {
+ if(read_cb(*data, 1, *length, handle) != *length)
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+ }
+
+ (*data)[*length] = '\0';
+
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
+}
+
+FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block)
+{
+ FLAC__Metadata_SimpleIteratorStatus status;
+ FLAC__byte buffer[4]; /* asserted below that this is big enough */
+ FLAC__uint32 len;
+
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8);
+
+ FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_TYPE_LEN % 8 == 0);
+ len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN / 8;
+ if(read_cb(buffer, 1, len, handle) != len)
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+ block->type = (FLAC__StreamMetadata_Picture_Type)unpack_uint32_(buffer, len);
+
+ if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, (FLAC__byte**)(&(block->mime_type)), &len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
+ return status;
+
+ if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->description), &len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
+ return status;
+
+ FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN % 8 == 0);
+ len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN / 8;
+ if(read_cb(buffer, 1, len, handle) != len)
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+ block->width = unpack_uint32_(buffer, len);
+
+ FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN % 8 == 0);
+ len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN / 8;
+ if(read_cb(buffer, 1, len, handle) != len)
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+ block->height = unpack_uint32_(buffer, len);
+
+ FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN % 8 == 0);
+ len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN / 8;
+ if(read_cb(buffer, 1, len, handle) != len)
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+ block->depth = unpack_uint32_(buffer, len);
+
+ /* for convenience we use read_metadata_block_data_picture_cstring_cb_() even though it adds an extra terminating NUL we don't use */
+ if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->data), &(block->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK)
+ return status;
+
+ return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
+}
+
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length)
{
if(block_length == 0) {
@@ -2193,6 +2324,8 @@
return write_metadata_block_data_vorbis_comment_cb_(handle, write_cb, &block->data.vorbis_comment);
case FLAC__METADATA_TYPE_CUESHEET:
return write_metadata_block_data_cuesheet_cb_(handle, write_cb, &block->data.cue_sheet);
+ case FLAC__METADATA_TYPE_PICTURE:
+ return write_metadata_block_data_picture_cb_(handle, write_cb, &block->data.picture);
default:
return write_metadata_block_data_unknown_cb_(handle, write_cb, &block->data.unknown, block->length);
}
@@ -2285,7 +2418,7 @@
const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
FLAC__byte buffer[4]; /* magic number is asserted below */
- FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == 4);
+ FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == sizeof(buffer));
pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len);
if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
@@ -2402,6 +2535,73 @@
return true;
}
+FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block)
+{
+ unsigned len;
+ size_t slen;
+ FLAC__byte buffer[4]; /* magic number is asserted below */
+
+ FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_TYPE_LEN%8);
+ FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN%8);
+ FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN%8);
+ FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN%8);
+ FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN%8);
+ FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN%8);
+ FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN%8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8);
+ FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8);
+
+ len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8;
+ pack_uint32_(block->type, buffer, len);
+ if(write_cb(buffer, 1, len, handle) != len)
+ return false;
+
+ len = FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8;
+ slen = strlen(block->mime_type);
+ pack_uint32_(slen, buffer, len);
+ if(write_cb(buffer, 1, len, handle) != len)
+ return false;
+ if(write_cb(block->mime_type, 1, slen, handle) != slen)
+ return false;
+
+ len = FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8;
+ slen = strlen((const char *)block->description);
+ pack_uint32_(slen, buffer, len);
+ if(write_cb(buffer, 1, len, handle) != len)
+ return false;
+ if(write_cb(block->description, 1, slen, handle) != slen)
+ return false;
+
+ len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8;
+ pack_uint32_(block->width, buffer, len);
+ if(write_cb(buffer, 1, len, handle) != len)
+ return false;
+
+ len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8;
+ pack_uint32_(block->height, buffer, len);
+ if(write_cb(buffer, 1, len, handle) != len)
+ return false;
+
+ len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8;
+ pack_uint32_(block->depth, buffer, len);
+ if(write_cb(buffer, 1, len, handle) != len)
+ return false;
+
+ len = FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8;
+ pack_uint32_(block->data_length, buffer, len);
+ if(write_cb(buffer, 1, len, handle) != len)
+ return false;
+ if(write_cb(block->data, 1, block->data_length, handle) != block->data_length)
+ return false;
+
+ return true;
+}
+
FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length)
{
if(write_cb(block->data, 1, block_length, handle) != block_length)
@@ -2556,7 +2756,7 @@
size_t n;
unsigned i;
- FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == 4);
+ FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == sizeof(buffer));
/* skip any id3v2 tag */
errno = 0;
diff --git a/src/libFLAC/metadata_object.c b/src/libFLAC/metadata_object.c
index 6846c3b..7efa2cf 100644
--- a/src/libFLAC/metadata_object.c
+++ b/src/libFLAC/metadata_object.c
@@ -47,8 +47,17 @@
*
***************************************************************************/
+/* copy bytes:
+ * from = NULL && bytes = 0
+ * to <- NULL
+ * from != NULL && bytes > 0
+ * to <- copy of from
+ * else ASSERT
+ * malloc error leaved 'to' unchanged
+ */
static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
{
+ FLAC__ASSERT(0 != to);
if(bytes > 0 && 0 != from) {
FLAC__byte *x;
if(0 == (x = (FLAC__byte*)malloc(bytes)))
@@ -64,6 +73,25 @@
return true;
}
+#if 0 /* UNUSED */
+/* like copy_bytes_(), but free()s the original '*to' if the copy succeeds and the original '*to' is non-NULL */
+static FLAC__bool free_copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes)
+{
+ FLAC__byte *copy;
+ FLAC__ASSERT(0 != to);
+ if(copy_bytes_(©, from, bytes)) {
+ if(*to)
+ free(*to);
+ *to = copy;
+ return true;
+ }
+ else
+ return false;
+}
+#endif
+
+/* reallocate entry to 1 byte larger and add a terminating NUL */
+/* realloc() failure leaves entry unchanged */
static FLAC__bool ensure_null_terminated_(FLAC__byte **entry, unsigned length)
{
FLAC__byte *x = (FLAC__byte*)realloc(*entry, length+1);
@@ -76,6 +104,24 @@
return false;
}
+/* copies the NUL-terminated C-string 'from' to '*to', leaving '*to'
+ * unchanged if malloc fails, free()ing the original '*to' if it
+ * succeeds and the original '*to' was not NULL
+ */
+static FLAC__bool copy_cstring_(char **to, const char *from)
+{
+ FLAC__ASSERT(to);
+ char *copy = strdup(from);
+ if(copy) {
+ if(*to)
+ free(*to);
+ *to = copy;
+ return true;
+ }
+ else
+ return false;
+}
+
static FLAC__bool copy_vcentry_(FLAC__StreamMetadata_VorbisComment_Entry *to, const FLAC__StreamMetadata_VorbisComment_Entry *from)
{
to->length = from->length;
@@ -417,18 +463,49 @@
*/
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
- {
- object->data.vorbis_comment.vendor_string.length = (unsigned)strlen(FLAC__VENDOR_STRING);
- if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, (const FLAC__byte*)FLAC__VENDOR_STRING, object->data.vorbis_comment.vendor_string.length+1)) {
- free(object);
- return 0;
- }
- vorbiscomment_calculate_length_(object);
+ object->data.vorbis_comment.vendor_string.length = (unsigned)strlen(FLAC__VENDOR_STRING);
+ if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, (const FLAC__byte*)FLAC__VENDOR_STRING, object->data.vorbis_comment.vendor_string.length+1)) {
+ free(object);
+ return 0;
}
+ vorbiscomment_calculate_length_(object);
break;
case FLAC__METADATA_TYPE_CUESHEET:
cuesheet_calculate_length_(object);
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ object->length = (
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+ FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* empty mime_type string */
+ FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* empty description string */
+ FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN +
+ 0 /* no data */
+ ) / 8;
+ object->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER;
+ object->data.picture.mime_type = 0;
+ object->data.picture.description = 0;
+ /* calloc() took care of this for us:
+ object->data.picture.width = 0;
+ object->data.picture.height = 0;
+ object->data.picture.depth = 0;
+ object->data.picture.data_length = 0;
+ object->data.picture.data = 0;
+ */
+ /* now initialize mime_type and description with empty strings to make things easier on the client */
+ if(!copy_cstring_(&object->data.picture.mime_type, "")) {
+ free(object);
+ return 0;
+ }
+ if(!copy_cstring_((char**)(&object->data.picture.description), "")) {
+ if(object->data.picture.mime_type)
+ free(object->data.picture.mime_type);
+ free(object);
+ return 0;
+ }
+ break;
default:
/* calloc() took care of this for us:
object->length = 0;
@@ -508,6 +585,25 @@
}
}
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ to->data.picture.type = object->data.picture.type;
+ if(!copy_cstring_(&to->data.picture.mime_type, object->data.picture.mime_type)) {
+ FLAC__metadata_object_delete(to);
+ return 0;
+ }
+ if(!copy_cstring_((char**)(&to->data.picture.description), (const char*)object->data.picture.description)) {
+ FLAC__metadata_object_delete(to);
+ return 0;
+ }
+ to->data.picture.width = object->data.picture.width;
+ to->data.picture.height = object->data.picture.height;
+ to->data.picture.depth = object->data.picture.depth;
+ to->data.picture.data_length = object->data.picture.data_length;
+ if(!copy_bytes_((&to->data.picture.data), object->data.picture.data, object->data.picture.data_length)) {
+ FLAC__metadata_object_delete(to);
+ return 0;
+ }
+ break;
default:
if(!copy_bytes_(&to->data.unknown.data, object->data.unknown.data, object->length)) {
FLAC__metadata_object_delete(to);
@@ -556,6 +652,20 @@
cuesheet_track_array_delete_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks);
}
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ if(0 != object->data.picture.mime_type) {
+ free(object->data.picture.mime_type);
+ object->data.picture.mime_type = 0;
+ }
+ if(0 != object->data.picture.description) {
+ free(object->data.picture.description);
+ object->data.picture.description = 0;
+ }
+ if(0 != object->data.picture.data) {
+ free(object->data.picture.data);
+ object->data.picture.data = 0;
+ }
+ break;
default:
if(0 != object->data.unknown.data) {
free(object->data.unknown.data);
@@ -710,6 +820,27 @@
return true;
}
+static FLAC__bool compare_block_data_picture_(const FLAC__StreamMetadata_Picture *block1, const FLAC__StreamMetadata_Picture *block2)
+{
+ if(block1->type != block2->type)
+ return false;
+ if(block1->mime_type != block2->mime_type && (0 == block1->mime_type || 0 == block2->mime_type || strcmp(block1->mime_type, block2->mime_type)))
+ return false;
+ if(block1->description != block2->description && (0 == block1->description || 0 == block2->description || strcmp((const char *)block1->description, (const char *)block2->description)))
+ return false;
+ if(block1->width != block2->width)
+ return false;
+ if(block1->height != block2->height)
+ return false;
+ if(block1->depth != block2->depth)
+ return false;
+ if(block1->data_length != block2->data_length)
+ return false;
+ if(block1->data != block2->data && (0 == block1->data || 0 == block2->data || memcmp(block1->data, block2->data, block1->data_length)))
+ return false;
+ return true;
+}
+
static FLAC__bool compare_block_data_unknown_(const FLAC__StreamMetadata_Unknown *block1, const FLAC__StreamMetadata_Unknown *block2, unsigned block_length)
{
FLAC__ASSERT(0 != block1);
@@ -748,6 +879,8 @@
return compare_block_data_vorbiscomment_(&block1->data.vorbis_comment, &block2->data.vorbis_comment);
case FLAC__METADATA_TYPE_CUESHEET:
return compare_block_data_cuesheet_(&block1->data.cue_sheet, &block2->data.cue_sheet);
+ case FLAC__METADATA_TYPE_PICTURE:
+ return compare_block_data_picture_(&block1->data.picture, &block2->data.picture);
default:
return compare_block_data_unknown_(&block1->data.unknown, &block2->data.unknown, block1->length);
}
@@ -1553,3 +1686,99 @@
return (sum % 0xFF) << 24 | length << 8 | (FLAC__uint32)(cs->num_tracks-1);
}
}
+
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy)
+{
+ char *old;
+ size_t old_length, new_length;
+
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
+ FLAC__ASSERT(0 != mime_type);
+
+ old = object->data.picture.mime_type;
+ old_length = old? strlen(old) : 0;
+ new_length = strlen(mime_type);
+
+ /* do the copy first so that if we fail we leave the object untouched */
+ if(copy) {
+ if(!copy_bytes_((FLAC__byte**)(&object->data.picture.mime_type), (FLAC__byte*)mime_type, new_length+1))
+ return false;
+ }
+ else {
+ object->data.picture.mime_type = mime_type;
+ }
+
+ if(0 != old)
+ free(old);
+
+ object->length -= old_length;
+ object->length += new_length;
+ return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy)
+{
+ FLAC__byte *old;
+ size_t old_length, new_length;
+
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
+ FLAC__ASSERT(0 != description);
+
+ old = object->data.picture.description;
+ old_length = old? strlen((const char *)old) : 0;
+ new_length = strlen((const char *)description);
+
+ /* do the copy first so that if we fail we leave the object untouched */
+ if(copy) {
+ if(!copy_bytes_(&object->data.picture.description, description, new_length+1))
+ return false;
+ }
+ else {
+ object->data.picture.description = description;
+ }
+
+ if(0 != old)
+ free(old);
+
+ object->length -= old_length;
+ object->length += new_length;
+ return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy)
+{
+ FLAC__byte *old;
+
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
+ FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false));
+
+ old = object->data.picture.data;
+
+ /* do the copy first so that if we fail we leave the object untouched */
+ if(copy) {
+ if(!copy_bytes_(&object->data.picture.data, data, length))
+ return false;
+ }
+ else {
+ object->data.picture.data = data;
+ }
+
+ if(0 != old)
+ free(old);
+
+ object->length -= object->data.picture.data_length;
+ object->data.picture.data_length = length;
+ object->length += length;
+ return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation)
+{
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE);
+
+ return FLAC__format_picture_is_legal(&object->data.picture, violation);
+}
diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c
index d64280d..802d495 100644
--- a/src/libFLAC/stream_decoder.c
+++ b/src/libFLAC/stream_decoder.c
@@ -99,6 +99,7 @@
static FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length);
static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj);
static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj);
+static FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj);
static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder);
static FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder);
static FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode);
@@ -1296,6 +1297,10 @@
if(!read_metadata_cuesheet_(decoder, &block.data.cue_sheet))
return false;
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ if(!read_metadata_picture_(decoder, &block.data.picture))
+ return false;
+ break;
case FLAC__METADATA_TYPE_STREAMINFO:
case FLAC__METADATA_TYPE_SEEKTABLE:
FLAC__ASSERT(0);
@@ -1342,6 +1347,14 @@
if(0 != block.data.cue_sheet.tracks)
free(block.data.cue_sheet.tracks);
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ if(0 != block.data.picture.mime_type)
+ free(block.data.picture.mime_type);
+ if(0 != block.data.picture.description)
+ free(block.data.picture.description);
+ if(0 != block.data.picture.data)
+ free(block.data.picture.data);
+ break;
case FLAC__METADATA_TYPE_STREAMINFO:
case FLAC__METADATA_TYPE_SEEKTABLE:
FLAC__ASSERT(0);
@@ -1616,6 +1629,69 @@
return true;
}
+FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj)
+{
+ FLAC__uint32 len;
+
+ FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(decoder->private_->input));
+
+ /* read type */
+ if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &obj->type, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+
+ /* read MIME type */
+ if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+ if(0 == (obj->mime_type = (char*)malloc(len+1))) {
+ decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+ return false;
+ }
+ if(len > 0) {
+ if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->mime_type, len, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+ }
+ obj->mime_type[len] = '\0';
+
+ /* read description */
+ if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+ if(0 == (obj->description = (FLAC__byte*)malloc(len+1))) {
+ decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+ return false;
+ }
+ if(len > 0) {
+ if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->description, len, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+ }
+ obj->description[len] = '\0';
+
+ /* read width */
+ if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &obj->width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+
+ /* read height */
+ if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &obj->height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+
+ /* read depth */
+ if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &obj->depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+
+ /* read data */
+ if(!FLAC__bitbuffer_read_raw_uint32(decoder->private_->input, &(obj->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+ if(0 == (obj->data = (FLAC__byte*)malloc(obj->data_length))) {
+ decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+ return false;
+ }
+ if(obj->data_length > 0) {
+ if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, obj->data, obj->data_length, read_callback_, decoder))
+ return false; /* read_callback_ sets the state for us */
+ }
+
+ return true;
+}
+
FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder)
{
FLAC__uint32 x;
diff --git a/src/libFLAC/stream_encoder.c b/src/libFLAC/stream_encoder.c
index be11e5e..407346f 100644
--- a/src/libFLAC/stream_encoder.c
+++ b/src/libFLAC/stream_encoder.c
@@ -773,6 +773,10 @@
if(!FLAC__format_cuesheet_is_legal(&encoder->protected_->metadata[i]->data.cue_sheet, encoder->protected_->metadata[i]->data.cue_sheet.is_cd, /*violation=*/0))
return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
}
+ else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_PICTURE) {
+ if(!FLAC__format_picture_is_legal(&encoder->protected_->metadata[i]->data.picture, /*violation=*/0))
+ return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
+ }
}
encoder->private_->input_capacity = 0;
diff --git a/src/libFLAC/stream_encoder_framing.c b/src/libFLAC/stream_encoder_framing.c
index 87611b7..29bde9e 100644
--- a/src/libFLAC/stream_encoder_framing.c
+++ b/src/libFLAC/stream_encoder_framing.c
@@ -177,6 +177,33 @@
}
}
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ {
+ size_t len;
+ if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.type, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN))
+ return false;
+ len = strlen(metadata->data.picture.mime_type);
+ if(!FLAC__bitbuffer_write_raw_uint32(bb, len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN))
+ return false;
+ if(!FLAC__bitbuffer_write_byte_block(bb, (const FLAC__byte*)metadata->data.picture.mime_type, len))
+ return false;
+ len = strlen((const char *)metadata->data.picture.description);
+ if(!FLAC__bitbuffer_write_raw_uint32(bb, len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN))
+ return false;
+ if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.picture.description, len))
+ return false;
+ if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN))
+ return false;
+ if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN))
+ return false;
+ if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN))
+ return false;
+ if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.picture.data_length, FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN))
+ return false;
+ if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.picture.data, metadata->data.picture.data_length))
+ return false;
+ }
+ break;
default:
if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.unknown.data, metadata->length))
return false;
diff --git a/src/metaflac/operations.c b/src/metaflac/operations.c
index a2a7d7f..aad872b 100644
--- a/src/metaflac/operations.c
+++ b/src/metaflac/operations.c
@@ -646,6 +646,18 @@
}
}
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ PPR; printf(" type: %u (%s)\n", block->data.picture.type, block->data.picture.type < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED? FLAC__StreamMetadata_Picture_TypeString[block->data.picture.type] : "UNDEFINED");
+ PPR; printf(" MIME type: %s\n", block->data.picture.mime_type);
+ PPR; printf(" description: %s\n", block->data.picture.description);
+ PPR; printf(" width: %u\n", (unsigned)block->data.picture.width);
+ PPR; printf(" height: %u\n", (unsigned)block->data.picture.height);
+ PPR; printf(" depth: %u\n", (unsigned)block->data.picture.depth);
+ PPR; printf(" data length: %u\n", (unsigned)block->data.picture.data_length);
+ PPR; printf(" data:\n");
+ if(0 != block->data.picture.data)
+ hexdump(filename, block->data.picture.data, block->data.picture.data_length, " ");
+ break;
default:
PPR; printf(" data contents:\n");
if(0 != block->data.unknown.data)
diff --git a/src/test_libFLAC++/decoders.cpp b/src/test_libFLAC++/decoders.cpp
index 486af3b..976342d 100644
--- a/src/test_libFLAC++/decoders.cpp
+++ b/src/test_libFLAC++/decoders.cpp
@@ -58,8 +58,8 @@
"Filename"
};
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static ::FLAC__StreamMetadata *expected_metadata_sequence_[8];
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static ::FLAC__StreamMetadata *expected_metadata_sequence_[9];
static unsigned num_expected_;
static const char *flacfilename_ = "metadata.flac";
static off_t flacfilesize_;
@@ -86,12 +86,12 @@
static void init_metadata_blocks_()
{
- mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static void free_metadata_blocks_()
{
- mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static bool generate_file_()
@@ -105,6 +105,7 @@
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!file_utils__generate_flacfile(flacfilename_, &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
@@ -710,6 +711,7 @@
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -756,6 +758,7 @@
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -785,6 +788,7 @@
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -815,6 +819,7 @@
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -851,6 +856,7 @@
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -993,6 +999,7 @@
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
diff --git a/src/test_libFLAC++/encoders.cpp b/src/test_libFLAC++/encoders.cpp
index 24845b8..94124b9 100644
--- a/src/test_libFLAC++/encoders.cpp
+++ b/src/test_libFLAC++/encoders.cpp
@@ -42,8 +42,8 @@
"Filename"
};
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static ::FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_ };
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static ::FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_ };
static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
static const char *flacfilename_ = "metadata.flac";
@@ -73,12 +73,12 @@
static void init_metadata_blocks_()
{
- mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static void free_metadata_blocks_()
{
- mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
class StreamEncoder : public FLAC::Encoder::Stream {
diff --git a/src/test_libFLAC++/metadata_manip.cpp b/src/test_libFLAC++/metadata_manip.cpp
index a813813..cf27b9e 100644
--- a/src/test_libFLAC++/metadata_manip.cpp
+++ b/src/test_libFLAC++/metadata_manip.cpp
@@ -106,6 +106,16 @@
return x;
}
+static char *strdup_or_die_(const char *s)
+{
+ char *x = strdup(s);
+ if(0 == x) {
+ fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
+ exit(1);
+ }
+ return x;
+}
+
/* functions for working with our metadata copy */
static bool replace_in_our_metadata_(FLAC::Metadata::Prototype *block, unsigned position, bool copy)
@@ -474,10 +484,10 @@
printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
}
-static bool generate_file_(FLAC__bool include_cuesheet)
+static bool generate_file_(FLAC__bool include_extras)
{
- ::FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
- ::FLAC__StreamMetadata *metadata[3];
+ ::FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
+ ::FLAC__StreamMetadata *metadata[4];
unsigned i = 0, n = 0;
printf("generating FLAC file for test\n");
@@ -524,23 +534,54 @@
return die_("priming our metadata");
}
+ {
+ picture.is_last = false;
+ picture.type = ::FLAC__METADATA_TYPE_PICTURE;
+ picture.length =
+ (
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+ FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
+ FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
+ FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
+ ) / 8
+ ;
+ picture.data.picture.type = ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
+ picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
+ picture.length += strlen(picture.data.picture.mime_type);
+ picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
+ picture.length += strlen((const char *)picture.data.picture.description);
+ picture.data.picture.width = 300;
+ picture.data.picture.height = 300;
+ picture.data.picture.depth = 24;
+ picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
+ picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
+ picture.length += picture.data.picture.data_length;
+ }
+
padding.is_last = true;
padding.type = ::FLAC__METADATA_TYPE_PADDING;
padding.length = 1234;
metadata[n++] = &vorbiscomment;
- if (include_cuesheet)
+ if(include_extras) {
metadata[n++] = cuesheet;
+ metadata[n++] = &picture;
+ }
metadata[n++] = &padding;
FLAC::Metadata::StreamInfo s(&streaminfo);
FLAC::Metadata::VorbisComment v(&vorbiscomment);
FLAC::Metadata::CueSheet c(cuesheet, /*copy=*/false);
+ FLAC::Metadata::Picture pi(&picture);
FLAC::Metadata::Padding p(&padding);
if(
!insert_to_our_metadata_(&s, i++, /*copy=*/true) ||
!insert_to_our_metadata_(&v, i++, /*copy=*/true) ||
- (include_cuesheet && !insert_to_our_metadata_(&v, i++, /*copy=*/true)) ||
+ (include_extras && !insert_to_our_metadata_(&c, i++, /*copy=*/true)) ||
+ (include_extras && !insert_to_our_metadata_(&pi, i++, /*copy=*/true)) ||
!insert_to_our_metadata_(&p, i++, /*copy=*/true)
)
return die_("priming our metadata");
@@ -616,7 +657,7 @@
printf("\n\n++++++ testing level 0 interface\n");
- if(!generate_file_(/*include_cuesheet=*/true))
+ if(!generate_file_(/*include_extras=*/true))
return false;
if(!test_file_(flacfile_, /*ignore_metadata=*/true))
@@ -705,6 +746,38 @@
printf("OK\n");
}
+ {
+ printf("testing FLAC::Metadata::get_picture(Picture *&)... ");
+
+ FLAC::Metadata::Picture *picture = 0;
+
+ if(!FLAC::Metadata::get_picture(flacfile_, picture, /*type=*/(::FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1)))
+ return die_("during FLAC::Metadata::get_picture()");
+
+ /* check to see if some basic data matches (c.f. generate_file_()) */
+ if(picture->get_type () != ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
+ return die_("mismatch in picture->get_type ()");
+
+ printf("OK\n");
+
+ delete picture;
+ }
+
+ {
+ printf("testing FLAC::Metadata::get_picture(Picture &)... ");
+
+ FLAC::Metadata::Picture picture;
+
+ if(!FLAC::Metadata::get_picture(flacfile_, picture, /*type=*/(::FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1)))
+ return die_("during FLAC::Metadata::get_picture()");
+
+ /* check to see if some basic data matches (c.f. generate_file_()) */
+ if(picture.get_type () != ::FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
+ return die_("mismatch in picture->get_type ()");
+
+ printf("OK\n");
+ }
+
if(!remove_file_(flacfile_))
return false;
@@ -729,7 +802,7 @@
{
printf("simple iterator on read-only file\n");
- if(!generate_file_(/*include_cuesheet=*/false))
+ if(!generate_file_(/*include_extras=*/false))
return false;
if(!change_stats_(flacfile_, /*read_only=*/true))
@@ -1394,7 +1467,7 @@
printf("generate read-only file\n");
- if(!generate_file_(/*include_cuesheet=*/false))
+ if(!generate_file_(/*include_extras=*/false))
return false;
if(!change_stats_(flacfile_, /*read_only=*/true))
@@ -1949,7 +2022,7 @@
printf("generate file\n");
- if(!generate_file_(/*include_cuesheet=*/false))
+ if(!generate_file_(/*include_extras=*/false))
return false;
printf("create chain\n");
diff --git a/src/test_libFLAC++/metadata_object.cpp b/src/test_libFLAC++/metadata_object.cpp
index 845fb1f..ccf41f5 100644
--- a/src/test_libFLAC++/metadata_object.cpp
+++ b/src/test_libFLAC++/metadata_object.cpp
@@ -22,7 +22,7 @@
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for memcmp() */
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application_, vorbiscomment_, cuesheet_;
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application_, vorbiscomment_, cuesheet_, picture_;
static bool die_(const char *msg)
{
@@ -40,6 +40,16 @@
return x;
}
+static char *strdup_or_die_(const char *s)
+{
+ char *x = strdup(s);
+ if(0 == x) {
+ fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
+ exit(1);
+ }
+ return x;
+}
+
static bool index_is_equal_(const ::FLAC__StreamMetadata_CueSheet_Index &index, const ::FLAC__StreamMetadata_CueSheet_Index &indexcopy)
{
if(indexcopy.offset != index.offset)
@@ -131,7 +141,7 @@
vorbiscomment_.data.vorbis_comment.comments[1].entry = (FLAC__byte*)malloc_or_die_(12+1);
memcpy(vorbiscomment_.data.vorbis_comment.comments[1].entry, "name3=value3", 12+1);
- cuesheet_.is_last = true;
+ cuesheet_.is_last = false;
cuesheet_.type = ::FLAC__METADATA_TYPE_CUESHEET;
cuesheet_.length =
/* cuesheet guts */
@@ -186,6 +196,31 @@
cuesheet_.data.cue_sheet.tracks[1].indices = (FLAC__StreamMetadata_CueSheet_Index*)malloc_or_die_(cuesheet_.data.cue_sheet.tracks[1].num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
cuesheet_.data.cue_sheet.tracks[1].indices[0].offset = 0;
cuesheet_.data.cue_sheet.tracks[1].indices[0].number = 1;
+
+ picture_.is_last = true;
+ picture_.type = FLAC__METADATA_TYPE_PICTURE;
+ picture_.length =
+ (
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+ FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
+ FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
+ FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
+ ) / 8
+ ;
+ picture_.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
+ picture_.data.picture.mime_type = strdup_or_die_("image/jpeg");
+ picture_.length += strlen(picture_.data.picture.mime_type);
+ picture_.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
+ picture_.length += strlen((const char *)picture_.data.picture.description);
+ picture_.data.picture.width = 300;
+ picture_.data.picture.height = 300;
+ picture_.data.picture.depth = 24;
+ picture_.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
+ picture_.data.picture.data_length = strlen((const char *)picture_.data.picture.data);
+ picture_.length += picture_.data.picture.data_length;
}
static void free_metadata_blocks_()
@@ -199,6 +234,9 @@
free(cuesheet_.data.cue_sheet.tracks[0].indices);
free(cuesheet_.data.cue_sheet.tracks[1].indices);
free(cuesheet_.data.cue_sheet.tracks);
+ free(picture_.data.picture.mime_type);
+ free(picture_.data.picture.description);
+ free(picture_.data.picture.data);
}
bool test_metadata_object_streaminfo()
@@ -223,7 +261,7 @@
{
FLAC::Metadata::StreamInfo blockcopy(block);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != block)
return die_("copy is not identical to original");
printf("OK\n");
@@ -237,7 +275,7 @@
{
FLAC::Metadata::StreamInfo blockcopy(streaminfo_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != streaminfo_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -248,7 +286,7 @@
{
FLAC::Metadata::StreamInfo blockcopy(&streaminfo_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != streaminfo_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -259,7 +297,7 @@
{
FLAC::Metadata::StreamInfo blockcopy(&streaminfo_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != streaminfo_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -271,7 +309,7 @@
::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&streaminfo_);
FLAC::Metadata::StreamInfo blockcopy(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != streaminfo_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -283,7 +321,7 @@
FLAC::Metadata::StreamInfo blockcopy;
blockcopy.assign(&streaminfo_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != streaminfo_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -296,7 +334,7 @@
FLAC::Metadata::StreamInfo blockcopy;
blockcopy.assign(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != streaminfo_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -307,7 +345,7 @@
{
FLAC::Metadata::StreamInfo blockcopy = block;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == block))
return die_("copy is not identical to original");
printf("OK\n");
@@ -318,7 +356,7 @@
{
FLAC::Metadata::StreamInfo blockcopy = streaminfo_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == streaminfo_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -329,7 +367,7 @@
{
FLAC::Metadata::StreamInfo blockcopy = &streaminfo_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == streaminfo_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -456,7 +494,7 @@
{
FLAC::Metadata::Padding blockcopy(block);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != block)
return die_("copy is not identical to original");
printf("OK\n");
@@ -470,7 +508,7 @@
{
FLAC::Metadata::Padding blockcopy(padding_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != padding_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -481,7 +519,7 @@
{
FLAC::Metadata::Padding blockcopy(&padding_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != padding_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -492,7 +530,7 @@
{
FLAC::Metadata::Padding blockcopy(&padding_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != padding_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -504,7 +542,7 @@
::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&padding_);
FLAC::Metadata::Padding blockcopy(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != padding_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -516,7 +554,7 @@
FLAC::Metadata::Padding blockcopy;
blockcopy.assign(&padding_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != padding_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -529,7 +567,7 @@
FLAC::Metadata::Padding blockcopy;
blockcopy.assign(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != padding_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -540,7 +578,7 @@
{
FLAC::Metadata::Padding blockcopy = block;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == block))
return die_("copy is not identical to original");
printf("OK\n");
@@ -551,7 +589,7 @@
{
FLAC::Metadata::Padding blockcopy = padding_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == padding_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -562,7 +600,7 @@
{
FLAC::Metadata::Padding blockcopy = &padding_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == padding_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -617,7 +655,7 @@
{
FLAC::Metadata::Application blockcopy(block);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != block)
return die_("copy is not identical to original");
printf("OK\n");
@@ -631,7 +669,7 @@
{
FLAC::Metadata::Application blockcopy(application_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != application_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -642,7 +680,7 @@
{
FLAC::Metadata::Application blockcopy(&application_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != application_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -653,7 +691,7 @@
{
FLAC::Metadata::Application blockcopy(&application_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != application_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -665,7 +703,7 @@
::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&application_);
FLAC::Metadata::Application blockcopy(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != application_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -677,7 +715,7 @@
FLAC::Metadata::Application blockcopy;
blockcopy.assign(&application_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != application_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -690,7 +728,7 @@
FLAC::Metadata::Application blockcopy;
blockcopy.assign(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != application_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -701,7 +739,7 @@
{
FLAC::Metadata::Application blockcopy = block;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == block))
return die_("copy is not identical to original");
printf("OK\n");
@@ -712,7 +750,7 @@
{
FLAC::Metadata::Application blockcopy = application_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == application_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -723,7 +761,7 @@
{
FLAC::Metadata::Application blockcopy = &application_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == application_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -787,7 +825,7 @@
{
FLAC::Metadata::SeekTable blockcopy(block);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != block)
return die_("copy is not identical to original");
printf("OK\n");
@@ -801,7 +839,7 @@
{
FLAC::Metadata::SeekTable blockcopy(seektable_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != seektable_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -812,7 +850,7 @@
{
FLAC::Metadata::SeekTable blockcopy(&seektable_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != seektable_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -823,7 +861,7 @@
{
FLAC::Metadata::SeekTable blockcopy(&seektable_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != seektable_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -835,7 +873,7 @@
::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&seektable_);
FLAC::Metadata::SeekTable blockcopy(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != seektable_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -847,7 +885,7 @@
FLAC::Metadata::SeekTable blockcopy;
blockcopy.assign(&seektable_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != seektable_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -860,7 +898,7 @@
FLAC::Metadata::SeekTable blockcopy;
blockcopy.assign(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != seektable_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -871,7 +909,7 @@
{
FLAC::Metadata::SeekTable blockcopy = block;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == block))
return die_("copy is not identical to original");
printf("OK\n");
@@ -882,7 +920,7 @@
{
FLAC::Metadata::SeekTable blockcopy = seektable_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == seektable_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -893,7 +931,7 @@
{
FLAC::Metadata::SeekTable blockcopy = &seektable_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == seektable_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -1140,7 +1178,7 @@
{
FLAC::Metadata::VorbisComment blockcopy(block);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != block)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1154,7 +1192,7 @@
{
FLAC::Metadata::VorbisComment blockcopy(vorbiscomment_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != vorbiscomment_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1165,7 +1203,7 @@
{
FLAC::Metadata::VorbisComment blockcopy(&vorbiscomment_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != vorbiscomment_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1176,7 +1214,7 @@
{
FLAC::Metadata::VorbisComment blockcopy(&vorbiscomment_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != vorbiscomment_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1188,7 +1226,7 @@
::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&vorbiscomment_);
FLAC::Metadata::VorbisComment blockcopy(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != vorbiscomment_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1200,7 +1238,7 @@
FLAC::Metadata::VorbisComment blockcopy;
blockcopy.assign(&vorbiscomment_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != vorbiscomment_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1213,7 +1251,7 @@
FLAC::Metadata::VorbisComment blockcopy;
blockcopy.assign(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != vorbiscomment_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1224,7 +1262,7 @@
{
FLAC::Metadata::VorbisComment blockcopy = block;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == block))
return die_("copy is not identical to original");
printf("OK\n");
@@ -1235,7 +1273,7 @@
{
FLAC::Metadata::VorbisComment blockcopy = vorbiscomment_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == vorbiscomment_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -1246,7 +1284,7 @@
{
FLAC::Metadata::VorbisComment blockcopy = &vorbiscomment_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == vorbiscomment_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -1518,7 +1556,7 @@
{
FLAC::Metadata::CueSheet blockcopy(block);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != block)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1532,7 +1570,7 @@
{
FLAC::Metadata::CueSheet blockcopy(cuesheet_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != cuesheet_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1543,7 +1581,7 @@
{
FLAC::Metadata::CueSheet blockcopy(&cuesheet_);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != cuesheet_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1554,7 +1592,7 @@
{
FLAC::Metadata::CueSheet blockcopy(&cuesheet_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != cuesheet_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1566,7 +1604,7 @@
::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&cuesheet_);
FLAC::Metadata::CueSheet blockcopy(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != cuesheet_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1578,7 +1616,7 @@
FLAC::Metadata::CueSheet blockcopy;
blockcopy.assign(&cuesheet_, /*copy=*/true);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != cuesheet_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1591,7 +1629,7 @@
FLAC::Metadata::CueSheet blockcopy;
blockcopy.assign(copy, /*copy=*/false);
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(blockcopy != cuesheet_)
return die_("copy is not identical to original");
printf("OK\n");
@@ -1602,7 +1640,7 @@
{
FLAC::Metadata::CueSheet blockcopy = block;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == block))
return die_("copy is not identical to original");
printf("OK\n");
@@ -1613,7 +1651,7 @@
{
FLAC::Metadata::CueSheet blockcopy = cuesheet_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == cuesheet_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -1624,7 +1662,7 @@
{
FLAC::Metadata::CueSheet blockcopy = &cuesheet_;
if(!blockcopy.is_valid())
- return die_("!block.is_valid()");
+ return die_("!blockcopy.is_valid()");
if(!(blockcopy == cuesheet_))
return die_("copy is not identical to original");
printf("OK\n");
@@ -1759,6 +1797,254 @@
return true;
}
+bool test_metadata_object_picture()
+{
+ unsigned expected_length;
+
+ printf("testing class FLAC::Metadata::Picture\n");
+
+ printf("testing Picture::Picture()... ");
+ FLAC::Metadata::Picture block;
+ if(!block.is_valid())
+ return die_("!block.is_valid()");
+ expected_length = (
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+ FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN
+ ) / 8;
+ if(block.get_length() != expected_length) {
+ printf("FAILED, bad length, expected %u, got %u\n", expected_length, block.get_length());
+ return false;
+ }
+ printf("OK\n");
+
+ printf("testing Picture::Picture(const Picture &)... +\n");
+ printf(" Picture::operator!=(const Picture &)... ");
+ {
+ FLAC::Metadata::Picture blockcopy(block);
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(blockcopy != block)
+ return die_("copy is not identical to original");
+ printf("OK\n");
+
+ printf("testing Picture::~Picture()... ");
+ }
+ printf("OK\n");
+
+ printf("testing Picture::Picture(const ::FLAC__StreamMetadata &)... +\n");
+ printf(" Picture::operator!=(const ::FLAC__StreamMetadata &)... ");
+ {
+ FLAC::Metadata::Picture blockcopy(picture_);
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(blockcopy != picture_)
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::Picture(const ::FLAC__StreamMetadata *)... +\n");
+ printf(" Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+ {
+ FLAC::Metadata::Picture blockcopy(&picture_);
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(blockcopy != picture_)
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::Picture(const ::FLAC__StreamMetadata *, copy=true)... +\n");
+ printf(" Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+ {
+ FLAC::Metadata::Picture blockcopy(&picture_, /*copy=*/true);
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(blockcopy != picture_)
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::Picture(const ::FLAC__StreamMetadata *, copy=false)... +\n");
+ printf(" Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+ {
+ ::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&picture_);
+ FLAC::Metadata::Picture blockcopy(copy, /*copy=*/false);
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(blockcopy != picture_)
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::assign(const ::FLAC__StreamMetadata *, copy=true)... +\n");
+ printf(" Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+ {
+ FLAC::Metadata::Picture blockcopy;
+ blockcopy.assign(&picture_, /*copy=*/true);
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(blockcopy != picture_)
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::assign(const ::FLAC__StreamMetadata *, copy=false)... +\n");
+ printf(" Picture::operator!=(const ::FLAC__StreamMetadata *)... ");
+ {
+ ::FLAC__StreamMetadata *copy = ::FLAC__metadata_object_clone(&picture_);
+ FLAC::Metadata::Picture blockcopy;
+ blockcopy.assign(copy, /*copy=*/false);
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(blockcopy != picture_)
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::operator=(const Picture &)... +\n");
+ printf(" Picture::operator==(const Picture &)... ");
+ {
+ FLAC::Metadata::Picture blockcopy = block;
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(!(blockcopy == block))
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::operator=(const ::FLAC__StreamMetadata &)... +\n");
+ printf(" Picture::operator==(const ::FLAC__StreamMetadata &)... ");
+ {
+ FLAC::Metadata::Picture blockcopy = picture_;
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(!(blockcopy == picture_))
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::operator=(const ::FLAC__StreamMetadata *)... +\n");
+ printf(" Picture::operator==(const ::FLAC__StreamMetadata *)... ");
+ {
+ FLAC::Metadata::Picture blockcopy = &picture_;
+ if(!blockcopy.is_valid())
+ return die_("!blockcopy.is_valid()");
+ if(!(blockcopy == picture_))
+ return die_("copy is not identical to original");
+ printf("OK\n");
+ }
+
+ printf("testing Picture::get_type()... ");
+ if(block.get_type() != ::FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER)
+ return die_("value mismatch, expected ::FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER");
+ printf("OK\n");
+
+ printf("testing Picture::set_type()... +\n");
+ printf(" Picture::get_type()... ");
+ block.set_type(::FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA);
+ if(block.get_type() != ::FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA)
+ return die_("value mismatch, expected ::FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA");
+ printf("OK\n");
+
+ printf("testing Picture::set_mime_type()... ");
+ if(!block.set_mime_type("qmage/jpeg"))
+ return die_("returned false");
+ printf("OK\n");
+ picture_.data.picture.mime_type[0] = 'q';
+
+ printf("testing Picture::get_mime_type()... ");
+ if(0 != strcmp(block.get_mime_type(), picture_.data.picture.mime_type))
+ return die_("value mismatch");
+ printf("OK\n");
+
+ printf("testing Picture::set_description()... ");
+ if(!block.set_description((const FLAC__byte*)"qesc"))
+ return die_("returned false");
+ printf("OK\n");
+ picture_.data.picture.description[0] = 'q';
+
+ printf("testing Picture::get_description()... ");
+ if(0 != strcmp((const char *)block.get_description(), (const char *)picture_.data.picture.description))
+ return die_("value mismatch");
+ printf("OK\n");
+
+ printf("testing Picture::get_width()... ");
+ if(block.get_width() != 0)
+ return die_("value mismatch, expected 0");
+ printf("OK\n");
+
+ printf("testing Picture::set_width()... +\n");
+ printf(" Picture::get_width()... ");
+ block.set_width(400);
+ if(block.get_width() != 400)
+ return die_("value mismatch, expected 400");
+ printf("OK\n");
+
+ printf("testing Picture::get_height()... ");
+ if(block.get_height() != 0)
+ return die_("value mismatch, expected 0");
+ printf("OK\n");
+
+ printf("testing Picture::set_height()... +\n");
+ printf(" Picture::get_height()... ");
+ block.set_height(200);
+ if(block.get_height() != 200)
+ return die_("value mismatch, expected 200");
+ printf("OK\n");
+
+ printf("testing Picture::get_depth()... ");
+ if(block.get_depth() != 0)
+ return die_("value mismatch, expected 0");
+ printf("OK\n");
+
+ printf("testing Picture::set_depth()... +\n");
+ printf(" Picture::get_depth()... ");
+ block.set_depth(16);
+ if(block.get_depth() != 16)
+ return die_("value mismatch, expected 16");
+ printf("OK\n");
+
+ printf("testing Picture::get_data_length()... ");
+ if(block.get_data_length() != 0)
+ return die_("value mismatch, expected 0");
+ printf("OK\n");
+
+ printf("testing Picture::set_data()... ");
+ if(!block.set_data((const FLAC__byte*)"qOMEJPEGDATA", strlen("qOMEJPEGDATA")))
+ return die_("returned false");
+ printf("OK\n");
+ picture_.data.picture.data[0] = 'q';
+
+ printf("testing Picture::get_data()... ");
+ if(block.get_data_length() != picture_.data.picture.data_length)
+ return die_("length mismatch");
+ if(0 != memcmp(block.get_data(), picture_.data.picture.data, picture_.data.picture.data_length))
+ return die_("value mismatch");
+ printf("OK\n");
+
+ printf("testing FLAC::Metadata::clone(const FLAC::Metadata::Prototype *)... ");
+ FLAC::Metadata::Prototype *clone_ = FLAC::Metadata::clone(&block);
+ if(0 == clone_)
+ return die_("returned NULL");
+ if(0 == dynamic_cast<FLAC::Metadata::Picture *>(clone_))
+ return die_("downcast is NULL");
+ if(*dynamic_cast<FLAC::Metadata::Picture *>(clone_) != block)
+ return die_("clone is not identical");
+ printf("OK\n");
+ printf("testing Picture::~Picture()... ");
+ delete clone_;
+ printf("OK\n");
+
+
+ printf("PASSED\n\n");
+ return true;
+}
+
bool test_metadata_object()
{
printf("\n+++ libFLAC++ unit test: metadata objects\n\n");
@@ -1783,6 +2069,9 @@
if(!test_metadata_object_cuesheet())
return false;
+ if(!test_metadata_object_picture())
+ return false;
+
free_metadata_blocks_();
return true;
diff --git a/src/test_libFLAC/decoders.c b/src/test_libFLAC/decoders.c
index 1ac22d4..3765853 100644
--- a/src/test_libFLAC/decoders.c
+++ b/src/test_libFLAC/decoders.c
@@ -58,8 +58,8 @@
FLAC__bool error_occurred;
} StreamDecoderClientData;
-static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static FLAC__StreamMetadata *expected_metadata_sequence_[8];
+static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static FLAC__StreamMetadata *expected_metadata_sequence_[9];
static unsigned num_expected_;
static const char *flacfilename_ = "metadata.flac";
static off_t flacfilesize_;
@@ -86,12 +86,12 @@
static void init_metadata_blocks_()
{
- mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static void free_metadata_blocks_()
{
- mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static FLAC__bool generate_file_()
@@ -105,6 +105,7 @@
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!file_utils__generate_flacfile(flacfilename_, &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
@@ -627,6 +628,7 @@
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -667,6 +669,7 @@
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -692,6 +695,7 @@
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -718,6 +722,7 @@
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -748,6 +753,7 @@
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -866,6 +872,7 @@
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
diff --git a/src/test_libFLAC/encoders.c b/src/test_libFLAC/encoders.c
index 053695f..f3e9788 100644
--- a/src/test_libFLAC/encoders.c
+++ b/src/test_libFLAC/encoders.c
@@ -45,8 +45,8 @@
"Filename"
};
-static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_ };
+static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_ };
static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
static const char *flacfilename_ = "metadata.flac";
@@ -76,12 +76,12 @@
static void init_metadata_blocks_()
{
- mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static void free_metadata_blocks_()
{
- mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static FLAC__StreamEncoderWriteStatus stream_encoder_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
diff --git a/src/test_libFLAC/metadata_manip.c b/src/test_libFLAC/metadata_manip.c
index 21a8fa4..81885fd 100644
--- a/src/test_libFLAC/metadata_manip.c
+++ b/src/test_libFLAC/metadata_manip.c
@@ -100,6 +100,16 @@
return x;
}
+static char *strdup_or_die_(const char *s)
+{
+ char *x = strdup(s);
+ if(0 == x) {
+ fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
+ exit(1);
+ }
+ return x;
+}
+
/* functions for working with our metadata copy */
static FLAC__bool replace_in_our_metadata_(FLAC__StreamMetadata *block, unsigned position, FLAC__bool copy)
@@ -485,10 +495,10 @@
printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
}
-static FLAC__bool generate_file_(FLAC__bool include_cuesheet)
+static FLAC__bool generate_file_(FLAC__bool include_extras)
{
- FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, padding;
- FLAC__StreamMetadata *metadata[3];
+ FLAC__StreamMetadata streaminfo, vorbiscomment, *cuesheet, picture, padding;
+ FLAC__StreamMetadata *metadata[4];
unsigned i = 0, n = 0;
printf("generating FLAC file for test\n");
@@ -535,19 +545,49 @@
return die_("priming our metadata");
}
+ {
+ picture.is_last = false;
+ picture.type = FLAC__METADATA_TYPE_PICTURE;
+ picture.length =
+ (
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+ FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
+ FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
+ FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
+ ) / 8
+ ;
+ picture.data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
+ picture.data.picture.mime_type = strdup_or_die_("image/jpeg");
+ picture.length += strlen(picture.data.picture.mime_type);
+ picture.data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
+ picture.length += strlen((const char *)picture.data.picture.description);
+ picture.data.picture.width = 300;
+ picture.data.picture.height = 300;
+ picture.data.picture.depth = 24;
+ picture.data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
+ picture.data.picture.data_length = strlen((const char *)picture.data.picture.data);
+ picture.length += picture.data.picture.data_length;
+ }
+
padding.is_last = true;
padding.type = FLAC__METADATA_TYPE_PADDING;
padding.length = 1234;
metadata[n++] = &vorbiscomment;
- if (include_cuesheet)
+ if(include_extras) {
metadata[n++] = cuesheet;
+ metadata[n++] = &picture;
+ }
metadata[n++] = &padding;
if(
!insert_to_our_metadata_(&streaminfo, i++, /*copy=*/true) ||
!insert_to_our_metadata_(&vorbiscomment, i++, /*copy=*/true) ||
- (include_cuesheet && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
+ (include_extras && !insert_to_our_metadata_(cuesheet, i++, /*copy=*/false)) ||
+ (include_extras && !insert_to_our_metadata_(&picture, i++, /*copy=*/true)) ||
!insert_to_our_metadata_(&padding, i++, /*copy=*/true)
)
return die_("priming our metadata");
@@ -627,10 +667,11 @@
FLAC__StreamMetadata streaminfo;
FLAC__StreamMetadata *tags = 0;
FLAC__StreamMetadata *cuesheet = 0;
+ FLAC__StreamMetadata *picture = 0;
printf("\n\n++++++ testing level 0 interface\n");
- if(!generate_file_(/*include_cuesheet=*/true))
+ if(!generate_file_(/*include_extras=*/true))
return false;
if(!test_file_(flacfile_, decoder_metadata_callback_null_))
@@ -675,12 +716,25 @@
/* check to see if some basic data matches (c.f. generate_file_()) */
if(cuesheet->data.cue_sheet.lead_in != 123)
- return die_("mismatch in cuesheet->data.vorbis_comment.num_comments");
+ return die_("mismatch in cuesheet->data.cue_sheet.lead_in");
printf("OK\n");
FLAC__metadata_object_delete(cuesheet);
+ printf("testing FLAC__metadata_get_picture()... ");
+
+ if(!FLAC__metadata_get_picture(flacfile_, &picture, /*type=*/(FLAC__StreamMetadata_Picture_Type)(-1), /*mime_type=*/0, /*description=*/0, /*max_width=*/(unsigned)(-1), /*max_height=*/(unsigned)(-1), /*max_depth=*/(unsigned)(-1)))
+ return die_("during FLAC__metadata_get_picture()");
+
+ /* check to see if some basic data matches (c.f. generate_file_()) */
+ if(picture->data.picture.type != FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
+ return die_("mismatch in picture->data.picture.type");
+
+ printf("OK\n");
+
+ FLAC__metadata_object_delete(picture);
+
if(!remove_file_(flacfile_))
return false;
@@ -703,7 +757,7 @@
printf("simple iterator on read-only file\n");
- if(!generate_file_(/*include_cuesheet=*/false))
+ if(!generate_file_(/*include_extras=*/false))
return false;
if(!change_stats_(flacfile_, /*read_only=*/true))
@@ -1362,7 +1416,7 @@
printf("generate read-only file\n");
- if(!generate_file_(/*include_cuesheet=*/false))
+ if(!generate_file_(/*include_extras=*/false))
return false;
if(!change_stats_(flacfile_, /*read_only=*/true))
@@ -1875,7 +1929,7 @@
printf("generate file\n");
- if(!generate_file_(/*include_cuesheet=*/false))
+ if(!generate_file_(/*include_extras=*/false))
return false;
printf("create chain\n");
diff --git a/src/test_libFLAC/metadata_object.c b/src/test_libFLAC/metadata_object.c
index 304df90..2939ed3 100644
--- a/src/test_libFLAC/metadata_object.c
+++ b/src/test_libFLAC/metadata_object.c
@@ -463,10 +463,43 @@
cs_calc_len_(block);
}
+static void pi_set_mime_type(FLAC__StreamMetadata *block, const char *s)
+{
+ if(block->data.picture.mime_type) {
+ block->length -= strlen(block->data.picture.mime_type);
+ free(block->data.picture.mime_type);
+ }
+ block->data.picture.mime_type = strdup(s);
+ FLAC__ASSERT(block->data.picture.mime_type);
+ block->length += strlen(block->data.picture.mime_type);
+}
+
+static void pi_set_description(FLAC__StreamMetadata *block, const FLAC__byte *s)
+{
+ if(block->data.picture.description) {
+ block->length -= strlen((const char *)block->data.picture.description);
+ free(block->data.picture.description);
+ }
+ block->data.picture.description = (FLAC__byte*)strdup((const char *)s);
+ FLAC__ASSERT(block->data.picture.description);
+ block->length += strlen((const char *)block->data.picture.description);
+}
+
+static void pi_set_data(FLAC__StreamMetadata *block, const FLAC__byte *data, FLAC__uint32 len)
+{
+ if(block->data.picture.data) {
+ block->length -= block->data.picture.data_length;
+ free(block->data.picture.data);
+ }
+ block->data.picture.data = (FLAC__byte*)strdup((const char *)data);
+ FLAC__ASSERT(block->data.picture.data);
+ block->data.picture.data_length = len;
+ block->length += len;
+}
FLAC__bool test_metadata_object()
{
- FLAC__StreamMetadata *block, *blockcopy, *vorbiscomment, *cuesheet;
+ FLAC__StreamMetadata *block, *blockcopy, *vorbiscomment, *cuesheet, *picture;
FLAC__StreamMetadata_SeekPoint seekpoint_array[14];
FLAC__StreamMetadata_VorbisComment_Entry entry;
FLAC__StreamMetadata_CueSheet_Index index;
@@ -1996,5 +2029,253 @@
printf("OK\n");
+ printf("testing PICTURE\n");
+
+ printf("testing FLAC__metadata_object_new()... ");
+ block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE);
+ if(0 == block) {
+ printf("FAILED, returned NULL\n");
+ return false;
+ }
+ expected_length = (
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+ FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN
+ ) / 8;
+ if(block->length != expected_length) {
+ printf("FAILED, bad length, expected %u, got %u\n", expected_length, block->length);
+ return false;
+ }
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_clone()... ");
+ picture = FLAC__metadata_object_clone(block);
+ if(0 == picture) {
+ printf("FAILED, returned NULL\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ pi_set_mime_type(picture, "image/png\t");
+ printf("testing FLAC__metadata_object_picture_set_mime_type(copy)...");
+ if(!FLAC__metadata_object_picture_set_mime_type(block, "image/png\t", /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_picture_is_legal()...");
+ {
+ const char *violation;
+ if(FLAC__metadata_object_picture_is_legal(block, &violation)) {
+ printf("FAILED, returned true when expecting false\n");
+ return false;
+ }
+ printf("returned false as expected, violation=\"%s\" OK\n", violation);
+ }
+
+ pi_set_mime_type(picture, "image/png");
+ printf("testing FLAC__metadata_object_picture_set_mime_type(copy)...");
+ if(!FLAC__metadata_object_picture_set_mime_type(block, "image/png", /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_picture_is_legal()...");
+ {
+ const char *violation;
+ if(!FLAC__metadata_object_picture_is_legal(block, &violation)) {
+ printf("FAILED, returned false, violation=\"%s\"\n", violation);
+ return false;
+ }
+ printf("OK\n");
+ }
+
+ pi_set_description(picture, (const FLAC__byte *)"DESCRIPTION\xff");
+ printf("testing FLAC__metadata_object_picture_set_description(copy)...");
+ if(!FLAC__metadata_object_picture_set_description(block, (FLAC__byte *)"DESCRIPTION\xff", /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_picture_is_legal()...");
+ {
+ const char *violation;
+ if(FLAC__metadata_object_picture_is_legal(block, &violation)) {
+ printf("FAILED, returned true when expecting false\n");
+ return false;
+ }
+ printf("returned false as expected, violation=\"%s\" OK\n", violation);
+ }
+
+ pi_set_description(picture, (const FLAC__byte *)"DESCRIPTION");
+ printf("testing FLAC__metadata_object_picture_set_description(copy)...");
+ if(!FLAC__metadata_object_picture_set_description(block, (FLAC__byte *)"DESCRIPTION", /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_picture_is_legal()...");
+ {
+ const char *violation;
+ if(!FLAC__metadata_object_picture_is_legal(block, &violation)) {
+ printf("FAILED, returned false, violation=\"%s\"\n", violation);
+ return false;
+ }
+ printf("OK\n");
+ }
+
+
+ pi_set_data(picture, (const FLAC__byte*)"PNGDATA", strlen("PNGDATA"));
+ printf("testing FLAC__metadata_object_picture_set_data(copy)...");
+ if(!FLAC__metadata_object_picture_set_data(block, (FLAC__byte*)"PNGDATA", strlen("PNGDATA"), /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_clone()... ");
+ blockcopy = FLAC__metadata_object_clone(block);
+ if(0 == blockcopy) {
+ printf("FAILED, returned NULL\n");
+ return false;
+ }
+ if(!mutils__compare_block(block, blockcopy))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_delete()... ");
+ FLAC__metadata_object_delete(blockcopy);
+ printf("OK\n");
+
+ pi_set_mime_type(picture, "image/png\t");
+ printf("testing FLAC__metadata_object_picture_set_mime_type(own)...");
+ if(!FLAC__metadata_object_picture_set_mime_type(block, strdup("image/png\t"), /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_picture_is_legal()...");
+ {
+ const char *violation;
+ if(FLAC__metadata_object_picture_is_legal(block, &violation)) {
+ printf("FAILED, returned true when expecting false\n");
+ return false;
+ }
+ printf("returned false as expected, violation=\"%s\" OK\n", violation);
+ }
+
+ pi_set_mime_type(picture, "image/png");
+ printf("testing FLAC__metadata_object_picture_set_mime_type(own)...");
+ if(!FLAC__metadata_object_picture_set_mime_type(block, strdup("image/png"), /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_picture_is_legal()...");
+ {
+ const char *violation;
+ if(!FLAC__metadata_object_picture_is_legal(block, &violation)) {
+ printf("FAILED, returned false, violation=\"%s\"\n", violation);
+ return false;
+ }
+ printf("OK\n");
+ }
+
+ pi_set_description(picture, (const FLAC__byte *)"DESCRIPTION\xff");
+ printf("testing FLAC__metadata_object_picture_set_description(own)...");
+ if(!FLAC__metadata_object_picture_set_description(block, (FLAC__byte *)strdup("DESCRIPTION\xff"), /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_picture_is_legal()...");
+ {
+ const char *violation;
+ if(FLAC__metadata_object_picture_is_legal(block, &violation)) {
+ printf("FAILED, returned true when expecting false\n");
+ return false;
+ }
+ printf("returned false as expected, violation=\"%s\" OK\n", violation);
+ }
+
+ pi_set_description(picture, (const FLAC__byte *)"DESCRIPTION");
+ printf("testing FLAC__metadata_object_picture_set_description(own)...");
+ if(!FLAC__metadata_object_picture_set_description(block, (FLAC__byte *)strdup("DESCRIPTION"), /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_picture_is_legal()...");
+ {
+ const char *violation;
+ if(!FLAC__metadata_object_picture_is_legal(block, &violation)) {
+ printf("FAILED, returned false, violation=\"%s\"\n", violation);
+ return false;
+ }
+ printf("OK\n");
+ }
+
+ pi_set_data(picture, (const FLAC__byte*)"PNGDATA", strlen("PNGDATA"));
+ printf("testing FLAC__metadata_object_picture_set_data(own)...");
+ if(!FLAC__metadata_object_picture_set_data(block, (FLAC__byte*)strdup("PNGDATA"), strlen("PNGDATA"), /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!mutils__compare_block(picture, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_clone()... ");
+ blockcopy = FLAC__metadata_object_clone(block);
+ if(0 == blockcopy) {
+ printf("FAILED, returned NULL\n");
+ return false;
+ }
+ if(!mutils__compare_block(block, blockcopy))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_delete()... ");
+ FLAC__metadata_object_delete(blockcopy);
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_delete()... ");
+ FLAC__metadata_object_delete(picture);
+ FLAC__metadata_object_delete(block);
+ printf("OK\n");
+
+
return true;
}
diff --git a/src/test_libOggFLAC++/decoders.cpp b/src/test_libOggFLAC++/decoders.cpp
index 0776d0b..9a91ab9 100644
--- a/src/test_libOggFLAC++/decoders.cpp
+++ b/src/test_libOggFLAC++/decoders.cpp
@@ -58,8 +58,8 @@
"Filename"
};
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static ::FLAC__StreamMetadata *expected_metadata_sequence_[8];
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static ::FLAC__StreamMetadata *expected_metadata_sequence_[9];
static unsigned num_expected_;
static const char *flacfilename_ = "metadata.ogg";
static off_t flacfilesize_;
@@ -90,12 +90,12 @@
static void init_metadata_blocks_()
{
- mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static void free_metadata_blocks_()
{
- mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static bool generate_file_()
@@ -109,6 +109,7 @@
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
/* WATCHOUT: the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
@@ -723,6 +724,7 @@
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -769,6 +771,7 @@
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -798,6 +801,7 @@
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -828,6 +832,7 @@
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -864,6 +869,7 @@
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
@@ -1006,6 +1012,7 @@
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond() : dynamic_cast<FileDecoder*>(decoder)->test_respond()))
diff --git a/src/test_libOggFLAC++/encoders.cpp b/src/test_libOggFLAC++/encoders.cpp
index d2c7f69..ce91c8e 100644
--- a/src/test_libOggFLAC++/encoders.cpp
+++ b/src/test_libOggFLAC++/encoders.cpp
@@ -42,8 +42,8 @@
"Filename"
};
-static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static ::FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &unknown_ };
+static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static ::FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &picture_, &unknown_ };
static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
static const char *flacfilename_ = "metadata.ogg";
@@ -77,12 +77,12 @@
static void init_metadata_blocks_()
{
- mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static void free_metadata_blocks_()
{
- mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
class StreamEncoder : public OggFLAC::Encoder::Stream {
diff --git a/src/test_libOggFLAC/decoders.c b/src/test_libOggFLAC/decoders.c
index f02abbc..4eea85d 100644
--- a/src/test_libOggFLAC/decoders.c
+++ b/src/test_libOggFLAC/decoders.c
@@ -59,8 +59,8 @@
FLAC__bool error_occurred;
} StreamDecoderClientData;
-static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static FLAC__StreamMetadata *expected_metadata_sequence_[8];
+static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static FLAC__StreamMetadata *expected_metadata_sequence_[9];
static unsigned num_expected_;
static const char *flacfilename_ = "metadata.ogg";
static off_t flacfilesize_;
@@ -91,12 +91,12 @@
static void init_metadata_blocks_()
{
- mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static void free_metadata_blocks_()
{
- mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static FLAC__bool generate_file_()
@@ -110,6 +110,7 @@
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
/* WATCHOUT: the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
@@ -643,6 +644,7 @@
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -683,6 +685,7 @@
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -708,6 +711,7 @@
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -734,6 +738,7 @@
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application2_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -764,6 +769,7 @@
expected_metadata_sequence_[num_expected_++] = &padding_;
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
@@ -882,6 +888,7 @@
expected_metadata_sequence_[num_expected_++] = &seektable_;
expected_metadata_sequence_[num_expected_++] = &application1_;
expected_metadata_sequence_[num_expected_++] = &cuesheet_;
+ expected_metadata_sequence_[num_expected_++] = &picture_;
expected_metadata_sequence_[num_expected_++] = &unknown_;
if(!stream_decoder_test_respond_(decoder, &decoder_client_data))
diff --git a/src/test_libOggFLAC/encoders.c b/src/test_libOggFLAC/encoders.c
index 871ead4..d7701a5 100644
--- a/src/test_libOggFLAC/encoders.c
+++ b/src/test_libOggFLAC/encoders.c
@@ -45,8 +45,8 @@
"Filename"
};
-static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, unknown_;
-static FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &unknown_ };
+static FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
+static FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &picture_, &unknown_ };
static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
static const char *flacfilename_ = "metadata.ogg";
@@ -80,12 +80,12 @@
static void init_metadata_blocks_()
{
- mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static void free_metadata_blocks_()
{
- mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &unknown_);
+ mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
}
static OggFLAC__StreamEncoderReadStatus stream_encoder_read_callback_(const OggFLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
diff --git a/src/test_libs_common/metadata_utils.c b/src/test_libs_common/metadata_utils.c
index 926a894..1c88251 100644
--- a/src/test_libs_common/metadata_utils.c
+++ b/src/test_libs_common/metadata_utils.c
@@ -289,6 +289,56 @@
return true;
}
+FLAC__bool mutils__compare_block_data_picture(const FLAC__StreamMetadata_Picture *block, const FLAC__StreamMetadata_Picture *blockcopy)
+{
+ size_t len, lencopy;
+ if(blockcopy->type != block->type) {
+ printf("FAILED, type mismatch, expected %u, got %u\n", (unsigned)block->type, (unsigned)blockcopy->type);
+ return false;
+ }
+ len = strlen(block->mime_type);
+ lencopy = strlen(blockcopy->mime_type);
+ if(lencopy != len) {
+ printf("FAILED, mime_type length mismatch, expected %u, got %u\n", (unsigned)len, (unsigned)lencopy);
+ return false;
+ }
+ if(strcmp(blockcopy->mime_type, block->mime_type)) {
+ printf("FAILED, mime_type mismatch, expected %s, got %s\n", block->mime_type, blockcopy->mime_type);
+ return false;
+ }
+ len = strlen((const char *)block->description);
+ lencopy = strlen((const char *)blockcopy->description);
+ if(lencopy != len) {
+ printf("FAILED, description length mismatch, expected %u, got %u\n", (unsigned)len, (unsigned)lencopy);
+ return false;
+ }
+ if(strcmp((const char *)blockcopy->description, (const char *)block->description)) {
+ printf("FAILED, description mismatch, expected %s, got %s\n", block->description, blockcopy->description);
+ return false;
+ }
+ if(blockcopy->width != block->width) {
+ printf("FAILED, width mismatch, expected %u, got %u\n", block->width, blockcopy->width);
+ return false;
+ }
+ if(blockcopy->height != block->height) {
+ printf("FAILED, height mismatch, expected %u, got %u\n", block->height, blockcopy->height);
+ return false;
+ }
+ if(blockcopy->depth != block->depth) {
+ printf("FAILED, depth mismatch, expected %u, got %u\n", block->depth, blockcopy->depth);
+ return false;
+ }
+ if(blockcopy->data_length != block->data_length) {
+ printf("FAILED, data_length mismatch, expected %u, got %u\n", block->data_length, blockcopy->data_length);
+ return false;
+ }
+ if(memcmp(blockcopy->data, block->data, block->data_length)) {
+ printf("FAILED, data mismatch\n");
+ return false;
+ }
+ return true;
+}
+
FLAC__bool mutils__compare_block_data_unknown(const FLAC__StreamMetadata_Unknown *block, const FLAC__StreamMetadata_Unknown *blockcopy, unsigned block_length)
{
if(0 == block->data || 0 == blockcopy->data) {
@@ -341,10 +391,13 @@
return mutils__compare_block_data_vorbiscomment(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
case FLAC__METADATA_TYPE_CUESHEET:
return mutils__compare_block_data_cuesheet(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
+ case FLAC__METADATA_TYPE_PICTURE:
+ return mutils__compare_block_data_picture(&block->data.picture, &blockcopy->data.picture);
default:
return mutils__compare_block_data_unknown(&block->data.unknown, &blockcopy->data.unknown, block->length);
}
}
+
static void *malloc_or_die_(size_t size)
{
void *x = malloc(size);
@@ -365,6 +418,16 @@
return x;
}
+static char *strdup_or_die_(const char *s)
+{
+ char *x = strdup(s);
+ if(0 == x) {
+ fprintf(stderr, "ERROR: out of memory copying string \"%s\"\n", s);
+ exit(1);
+ }
+ return x;
+}
+
void mutils__init_metadata_blocks(
FLAC__StreamMetadata *streaminfo,
FLAC__StreamMetadata *padding,
@@ -373,6 +436,7 @@
FLAC__StreamMetadata *application2,
FLAC__StreamMetadata *vorbiscomment,
FLAC__StreamMetadata *cuesheet,
+ FLAC__StreamMetadata *picture,
FLAC__StreamMetadata *unknown
)
{
@@ -503,6 +567,31 @@
cuesheet->data.cue_sheet.tracks[2].number = 170;
cuesheet->data.cue_sheet.tracks[2].num_indices = 0;
+ picture->is_last = false;
+ picture->type = FLAC__METADATA_TYPE_PICTURE;
+ picture->length =
+ (
+ FLAC__STREAM_METADATA_PICTURE_TYPE_LEN +
+ FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* will add the length for the string later */
+ FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* will add the length for the string later */
+ FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN +
+ FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN /* will add the length for the data later */
+ ) / 8
+ ;
+ picture->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER;
+ picture->data.picture.mime_type = strdup_or_die_("image/jpeg");
+ picture->length += strlen(picture->data.picture.mime_type);
+ picture->data.picture.description = (FLAC__byte*)strdup_or_die_("desc");
+ picture->length += strlen((const char *)picture->data.picture.description);
+ picture->data.picture.width = 300;
+ picture->data.picture.height = 300;
+ picture->data.picture.depth = 24;
+ picture->data.picture.data = (FLAC__byte*)strdup_or_die_("SOMEJPEGDATA");
+ picture->data.picture.data_length = strlen((const char *)picture->data.picture.data);
+ picture->length += picture->data.picture.data_length;
+
unknown->is_last = true;
unknown->type = 126;
unknown->length = 8;
@@ -518,6 +607,7 @@
FLAC__StreamMetadata *application2,
FLAC__StreamMetadata *vorbiscomment,
FLAC__StreamMetadata *cuesheet,
+ FLAC__StreamMetadata *picture,
FLAC__StreamMetadata *unknown
)
{
@@ -530,5 +620,8 @@
free(cuesheet->data.cue_sheet.tracks[0].indices);
free(cuesheet->data.cue_sheet.tracks[1].indices);
free(cuesheet->data.cue_sheet.tracks);
+ free(picture->data.picture.mime_type);
+ free(picture->data.picture.description);
+ free(picture->data.picture.data);
free(unknown->data.unknown.data);
}