implement new CUESHEET metadata block
diff --git a/include/FLAC/format.h b/include/FLAC/format.h
index 15d2d17..b4eb887 100644
--- a/include/FLAC/format.h
+++ b/include/FLAC/format.h
@@ -449,16 +449,19 @@
/**< <A HREF="../format.html#metadata_block_streaminfo">STREAMINFO</A> block */
FLAC__METADATA_TYPE_PADDING = 1,
- /**< <A HREF="../format.html#metadata_block_padding"PADDING</A> block */
+ /**< <A HREF="../format.html#metadata_block_padding">PADDING</A> block */
FLAC__METADATA_TYPE_APPLICATION = 2,
- /**< <A HREF="../format.html#metadata_block_application"APPLICATION</A> block */
+ /**< <A HREF="../format.html#metadata_block_application">APPLICATION</A> block */
FLAC__METADATA_TYPE_SEEKTABLE = 3,
- /**< <A HREF="../format.html#metadata_block_seektable"SEEKTABLE</A> block */
+ /**< <A HREF="../format.html#metadata_block_seektable">SEEKTABLE</A> block */
FLAC__METADATA_TYPE_VORBIS_COMMENT = 4,
- /**< <A HREF="../format.html#metadata_block_vorbis_comment"VORBISCOMMENT</A> block */
+ /**< <A HREF="../format.html#metadata_block_vorbis_comment">VORBISCOMMENT</A> block */
+
+ FLAC__METADATA_TYPE_CUESHEET = 5
+ /**< <A HREF="../format.html#metadata_block_cuesheet">CUESHEET</A> block */
} FLAC__MetadataType;
@@ -582,6 +585,82 @@
extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */
+/** XXX. (c.f. <A HREF="../format.html#XXX">format specification</A>)
+ */
+typedef struct {
+ FLAC__uint64 offset;
+ /**< The index offset from the beginning of the track, in samples.
+ * For CD-DA, the offset must be evenly divisible by 588 samples (588
+ * samples = 44100 samples/sec * 1/75th of a sec)
+ */
+
+ FLAC__byte number;
+ /**< The index number. For CD-DA, an index number of 0 corresponds
+ * to the track pregap. There must be at least one index in a track.
+ * The first index in a track must be 0 or 1 and subsequently index
+ * numbers must increase by 1.
+ */
+} FLAC__StreamMetadata_CueSheet_Index;
+
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == @@@@3*8 (bits) */
+
+
+/** XXX. (c.f. <A HREF="../format.html#XXX">format specification</A>)
+ */
+typedef struct {
+ FLAC__uint64 offset;
+ /**< The track offset from the beginning of the audio data, in samples.
+ * This track offset is the offset to the first index point of the
+ * track. Note that for CD-DA, the track's offset in the TOC is that
+ * of the track's INDEX 01 even if there is an INDEX 00.
+ *
+ * For CD-DA, the offset must be evenly divisible by 588 samples (588
+ * samples = 44100 samples/sec * 1/75th of a sec)
+ */
+
+ FLAC__byte number;
+ /**< The track number. A track number of 0 is not allowed to avoid
+ * conflicting with the CD-DA spec, which reserves this for the
+ * lead-in. For CD-DA the number must be 1-99, or 170 for the lead-out.
+ * It is not required but encouraged to start with track 1 and increase
+ * sequentially. A CUESHEET block is required to have a lead-out
+ * track; it is always the last track in the cuesheet and the number
+ * must be 170 for CD-DA.
+ */
+
+ char isrc[13]; /*@@@@ 12 ascii characters plus trailing '\0' */
+ unsigned type:1; /*@@@@q-channel control bit 3: 0=>audio, 1=>data (undefined for CD-DA, defined for CDROM) */
+ unsigned pre_emphasis:1; /*@@@@q-channel control bit 5: 0=>no pre-em, 1=>pre-em */
+ unsigned reserved:6;
+ FLAC__byte num_indices;
+ FLAC__StreamMetadata_CueSheet_Index *indices;
+} FLAC__StreamMetadata_CueSheet_Track;
+
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+@@@@12*8 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */
+
+
+/** FLAC CUESHEET structure. (c.f. <A HREF="../format.html#metadata_block_cuesheet">format specification</A>)
+ */
+typedef struct {
+ char media_catalog_number[129]; /*@@@@ for CD-DA: 13 ascii digits ('0'-'9') plus 116 trailing '\0' characters */
+ FLAC__uint64 lead_in; /*@@@@ length of lead-in in samples; required to compute some versions of CD TOC hashes; CD-DA says the lead-in must be digital silence and rippers don't save it by convention, so TRACK 00 is disallowed and instead we store only the length. The lead-in is the number of samples up to the first index point of the first track, \b not INDEX 01 of the first track. This is so applications can correctly compute a CD-DA TOC equivalent even when there is TRACK 01 INDEX 00 data. */
+ unsigned num_tracks;
+ FLAC__StreamMetadata_CueSheet_Track *tracks;
+} FLAC__StreamMetadata_CueSheet;
+
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */
+extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */
+
+
/** FLAC metadata block structure. (c.f. <A HREF="../format.html#metadata_block">format specification</A>)
*/
typedef struct {
@@ -601,6 +680,7 @@
FLAC__StreamMetadata_Application application;
FLAC__StreamMetadata_SeekTable seek_table;
FLAC__StreamMetadata_VorbisComment vorbis_comment;
+ FLAC__StreamMetadata_CueSheet cue_sheet;
} data;
/**< Polymorphic block data; use the \a type value to determine which
* to use. */
@@ -658,6 +738,27 @@
*/
FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table);
+/*@@@@ add to unit tests */
+/** Check a cue sheet to see if it conforms to the FLAC specification.
+ * See the format specification for limits on the contents of the
+ * cue sheet.
+ *
+ * \param cue_sheet A pointer to an existing cue sheet to be checked.
+ * \param check_cd_da_subset If \c true, check CUESHEET against more
+ * stringent requirements for a CD-DA (audio) disc.
+ * \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 cue_sheet != NULL \endcode
+ * \retval FLAC__bool
+ * \c false if cue sheet is illegal, else \c true.
+ */
+FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation);
+
/* \} */
#ifdef __cplusplus
diff --git a/include/FLAC/metadata.h b/include/FLAC/metadata.h
index f1392d0..3f414c8 100644
--- a/include/FLAC/metadata.h
+++ b/include/FLAC/metadata.h
@@ -1231,7 +1231,7 @@
*/
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, unsigned comment_num);
-/*@@@@ needs unit test still */
+/*@@@@ add to unit tests */
/** Check if the given Vorbis comment entry's field name matches the given
* field name.
*
@@ -1247,7 +1247,7 @@
*/
FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *field_name, unsigned field_name_length);
-/*@@@@ needs unit test still */
+/*@@@@ add to unit tests */
/** Find a Vorbis comment with the given field name.
*
* The search begins at entry number \a offset; use and offset of 0 to
@@ -1266,7 +1266,7 @@
*/
FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name);
-/*@@@@ needs unit test still */
+/*@@@@ add to unit tests */
/** Remove first Vorbis comment matching the given field name.
*
* \param object A pointer to an existing VORBIS_COMMENT object.
@@ -1280,7 +1280,7 @@
*/
FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entry_matching(FLAC__StreamMetadata *object, const char *field_name);
-/*@@@@ needs unit test still */
+/*@@@@ add to unit tests */
/** Remove all Vorbis comments matching the given field name.
*
* \param object A pointer to an existing VORBIS_COMMENT object.
@@ -1294,6 +1294,49 @@
*/
FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__StreamMetadata *object, const char *field_name);
+/*@@@@ document, add to unit tests */
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices);
+
+/*@@@@ document, add to unit tests */
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index);
+
+/*@@@@ document, add to unit tests */
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num);
+
+/*@@@@ document */
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks);
+
+/*@@@@ document */
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track track, FLAC__bool copy);
+
+/*@@@@ document */
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track track, FLAC__bool copy);
+
+/*@@@@ document */
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num);
+
+/*@@@@ add to unit tests */
+/** Check a cue sheet to see if it conforms to the FLAC specification.
+ * See the format specification for limits on the contents of the
+ * cue sheet.
+ *
+ * \param object A pointer to an existing CUESHEET object.
+ * \param check_cd_da_subset If \c true, check CUESHEET against more
+ * stringent requirements for a CD-DA (audio) disc.
+ * \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_CUESHEET \endcode
+ * \retval FLAC__bool
+ * \c false if cue sheet is illegal, else \c true.
+ */
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_is_legal(const FLAC__StreamMetadata *object, FLAC__bool check_cd_da_subset, const char **violation);
+
/* \} */
#ifdef __cplusplus
diff --git a/src/libFLAC/format.c b/src/libFLAC/format.c
index b1da684..c76f799 100644
--- a/src/libFLAC/format.c
+++ b/src/libFLAC/format.c
@@ -67,6 +67,22 @@
FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits @@@@3*/
+
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+12*8; /* bits @@@@12*/
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */
+
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */
+FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* 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 */
@@ -216,6 +232,80 @@
return j;
}
+FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation)
+{
+ unsigned i, j;
+
+ if(check_cd_da_subset) {
+ if(cue_sheet->lead_in < 2 * 44100) {
+ if(violation) *violation = "CD-DA cue sheet must have a lead-in length of at least 2 seconds";
+ return false;
+ }
+ if(cue_sheet->lead_in % 588 != 0) {
+ if(violation) *violation = "CD-DA cue sheet lead-in length must be evenly divisible by 588 samples";
+ return false;
+ }
+ }
+
+ if(cue_sheet->num_tracks == 0) {
+ if(violation) *violation = "cue sheet must have at least one track (the lead-out)";
+ return false;
+ }
+
+ if(check_cd_da_subset && cue_sheet->tracks[cue_sheet->num_tracks-1].number != 170) {
+ if(violation) *violation = "CD-DA cue sheet must have a lead-out track number 170 (0xAA)";
+ return false;
+ }
+
+ for(i = 0; i < cue_sheet->num_tracks; i++) {
+ if(cue_sheet->tracks[i].number == 0) {
+ if(violation) *violation = "cue sheet may not have a track number 0";
+ return false;
+ }
+
+ if(check_cd_da_subset) {
+ if(!((cue_sheet->tracks[i].number >= 1 && cue_sheet->tracks[i].number <= 99) || cue_sheet->tracks[i].number == 170)) {
+ if(violation) *violation = "CD-DA cue sheet track number must be 1-99 or 170";
+ return false;
+ }
+ }
+
+ if(check_cd_da_subset && cue_sheet->tracks[i].offset % 588 != 0) {
+ if(violation) *violation = "CD-DA cue sheet track offset must be evenly divisible by 588 samples";
+ return false;
+ }
+
+ if(cue_sheet->tracks[i].num_indices == 0) {
+ if(violation) *violation = "cue sheet track must have at least one index point";
+ return false;
+ }
+
+ if(cue_sheet->tracks[i].indices[0].number > 1) {
+ if(violation) *violation = "cue sheet track's first index number must be 0 or 1";
+ return false;
+ }
+
+ for(j = 0; j < cue_sheet->tracks[i].num_indices; j++) {
+ if(check_cd_da_subset && cue_sheet->tracks[i].indices[j].offset % 588 != 0) {
+ if(violation) *violation = "CD-DA cue sheet track index offset must be evenly divisible by 588 samples";
+ return false;
+ }
+
+ if(j > 0) {
+ if(cue_sheet->tracks[i].indices[j].number != cue_sheet->tracks[i].indices[j-1].number + 1) {
+ if(violation) *violation = "cue sheet track index numbers must increase by 1";
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+/*
+ * These routines are private to libFLAC
+ */
unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order)
{
return
diff --git a/src/libFLAC/metadata_object.c b/src/libFLAC/metadata_object.c
index 099113c..9adb6f5 100644
--- a/src/libFLAC/metadata_object.c
+++ b/src/libFLAC/metadata_object.c
@@ -66,6 +66,23 @@
return true;
}
+static FLAC__bool copy_track_(FLAC__StreamMetadata_CueSheet_Track *to, const FLAC__StreamMetadata_CueSheet_Track *from)
+{
+ memcpy(to, from, sizeof(FLAC__StreamMetadata_CueSheet_Track));
+ if(0 == from->indices) {
+ FLAC__ASSERT(from->num_indices == 0);
+ }
+ else {
+ FLAC__StreamMetadata_CueSheet_Index *x;
+ FLAC__ASSERT(from->num_indices > 0);
+ if(0 == (x = (FLAC__StreamMetadata_CueSheet_Index*)malloc(from->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index))))
+ return false;
+ memcpy(x, from->indices, from->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index));
+ to->indices = x;
+ }
+ return true;
+}
+
static void seektable_calculate_length_(FLAC__StreamMetadata *object)
{
FLAC__ASSERT(0 != object);
@@ -142,13 +159,6 @@
if(0 != return_array) {
unsigned i;
- /* Need to do this to set the pointers inside the comments to 0.
- * In case of an error in the following loop, the object will be
- * deleted and we don't want the destructor freeing uninitialized
- * pointers.
- */
- memset(return_array, 0, num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry));
-
for(i = 0; i < num_comments; i++) {
if(!copy_vcentry_(return_array+i, object_array+i)) {
vorbiscomment_entry_array_delete_(return_array, num_comments);
@@ -188,6 +198,120 @@
return true;
}
+static void cuesheet_calculate_length_(FLAC__StreamMetadata *object)
+{
+ unsigned i;
+
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+
+ object->length = (
+ FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
+ ) / 8;
+
+ object->length += object->data.cue_sheet.num_tracks * (
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
+ ) / 8;
+
+ for(i = 0; i < object->data.cue_sheet.num_tracks; i++) {
+ object->length += object->data.cue_sheet.tracks[i].num_indices * (
+ FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
+ ) / 8;
+ }
+}
+
+static FLAC__StreamMetadata_CueSheet_Index *cuesheet_track_index_array_new_(unsigned num_indices)
+{
+ FLAC__ASSERT(num_indices > 0);
+
+ return (FLAC__StreamMetadata_CueSheet_Index*)calloc(num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index));
+}
+
+static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_new_(unsigned num_tracks)
+{
+ FLAC__ASSERT(num_tracks > 0);
+
+ return (FLAC__StreamMetadata_CueSheet_Track*)calloc(num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track));
+}
+
+static void cuesheet_track_array_delete_(FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks)
+{
+ unsigned i;
+
+ FLAC__ASSERT(0 != object_array && num_tracks > 0);
+
+ for(i = 0; i < num_tracks; i++) {
+ if(0 != object_array[i].indices) {
+ FLAC__ASSERT(object_array[i].num_indices > 0);
+ free(object_array[i].indices);
+ }
+ }
+
+ if(0 != object_array)
+ free(object_array);
+}
+
+static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_copy_(const FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks)
+{
+ FLAC__StreamMetadata_CueSheet_Track *return_array;
+
+ FLAC__ASSERT(0 != object_array);
+ FLAC__ASSERT(num_tracks > 0);
+
+ return_array = cuesheet_track_array_new_(num_tracks);
+
+ if(0 != return_array) {
+ unsigned i;
+
+ for(i = 0; i < num_tracks; i++) {
+ if(!copy_track_(return_array+i, object_array+i)) {
+ cuesheet_track_array_delete_(return_array, num_tracks);
+ return 0;
+ }
+ }
+ }
+
+ return return_array;
+}
+
+static FLAC__bool cuesheet_set_track_(FLAC__StreamMetadata *object, FLAC__StreamMetadata_CueSheet_Track *dest, const FLAC__StreamMetadata_CueSheet_Track *src, FLAC__bool copy)
+{
+ FLAC__StreamMetadata_CueSheet_Index *save;
+
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(0 != dest);
+ FLAC__ASSERT(0 != src);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+ FLAC__ASSERT((0 != src->indices && src->num_indices > 0) || (0 == src->indices && src->num_indices == 0));
+ /*@@@@ for docs, note that there is no "&& copy == false" at the end here ^^^ which will filter up */
+
+ save = dest->indices;
+
+ /* do the copy first so that if we fail we leave the object untouched */
+ if(copy) {
+ if(!copy_track_(dest, src))
+ return false;
+ }
+ else {
+ *dest = *src;
+ }
+
+ if(0 != save)
+ free(save);
+
+ cuesheet_calculate_length_(object);
+ return true;
+}
+
/****************************************************************************
*
@@ -219,13 +343,12 @@
free(object);
return 0;
}
- object->length =
- (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8) +
- object->data.vorbis_comment.vendor_string.length +
- (FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN/8)
- ;
+ vorbiscomment_calculate_length_(object);
}
break;
+ case FLAC__METADATA_TYPE_CUESHEET:
+ cuesheet_calculate_length_(object);
+ break;
default:
/* double protection: */
FLAC__ASSERT(0);
@@ -288,6 +411,20 @@
}
to->data.vorbis_comment.num_comments = object->data.vorbis_comment.num_comments;
break;
+ case FLAC__METADATA_TYPE_CUESHEET:
+ memcpy(&to->data.cue_sheet, &object->data.cue_sheet, sizeof(FLAC__StreamMetadata_CueSheet));
+ if(object->data.cue_sheet.num_tracks == 0) {
+ FLAC__ASSERT(0 == object->data.cue_sheet.tracks);
+ }
+ else {
+ FLAC__ASSERT(0 != object->data.cue_sheet.tracks);
+ to->data.cue_sheet.tracks = cuesheet_track_array_copy_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks);
+ if(0 == to->data.cue_sheet.tracks) {
+ FLAC__metadata_object_delete(to);
+ return 0;
+ }
+ }
+ break;
default:
/* double protection: */
FLAC__ASSERT(0);
@@ -323,6 +460,12 @@
vorbiscomment_entry_array_delete_(object->data.vorbis_comment.comments, object->data.vorbis_comment.num_comments);
}
break;
+ case FLAC__METADATA_TYPE_CUESHEET:
+ if(0 != object->data.cue_sheet.tracks) {
+ FLAC__ASSERT(object->data.cue_sheet.num_tracks > 0);
+ cuesheet_track_array_delete_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks);
+ }
+ break;
default:
FLAC__ASSERT(0);
}
@@ -424,6 +567,52 @@
return true;
}
+static FLAC__bool compare_block_data_cuesheet_(const FLAC__StreamMetadata_CueSheet *block1, const FLAC__StreamMetadata_CueSheet *block2)
+{
+ unsigned i, j;
+
+ if(0 != strcmp(block1->media_catalog_number, block2->media_catalog_number))
+ return false;
+
+ if(block1->lead_in != block2->lead_in)
+ return false;
+
+ if(block1->num_tracks != block2->num_tracks)
+ return false;
+
+ if(0 != block1->tracks && 0 != block2->tracks) {
+ FLAC__ASSERT(block1->num_tracks > 0);
+ for(i = 0; i < block1->num_tracks; i++) {
+ if(block1->tracks[i].offset != block2->tracks[i].offset)
+ return false;
+ if(block1->tracks[i].number != block2->tracks[i].number)
+ return false;
+ if(0 != memcmp(block1->tracks[i].isrc, block2->tracks[i].isrc, sizeof(block1->tracks[i].isrc)))
+ return false;
+ if(block1->tracks[i].type != block2->tracks[i].type)
+ return false;
+ if(block1->tracks[i].pre_emphasis != block2->tracks[i].pre_emphasis)
+ return false;
+ if(block1->tracks[i].num_indices != block2->tracks[i].num_indices)
+ return false;
+ if(0 != block1->tracks[i].indices && 0 != block2->tracks[i].indices) {
+ FLAC__ASSERT(block1->tracks[i].num_indices > 0);
+ for(j = 0; j < block1->tracks[i].num_indices; j++) {
+ if(block1->tracks[i].indices[j].offset != block2->tracks[i].indices[j].offset)
+ return false;
+ if(block1->tracks[i].indices[j].number != block2->tracks[i].indices[j].number)
+ return false;
+ }
+ }
+ else if(block1->tracks[i].indices != block2->tracks[i].indices)
+ return false;
+ }
+ }
+ else if(block1->tracks != block2->tracks)
+ return false;
+ return true;
+}
+
FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *block1, const FLAC__StreamMetadata *block2)
{
FLAC__ASSERT(0 != block1);
@@ -449,6 +638,8 @@
return compare_block_data_seektable_(&block1->data.seek_table, &block2->data.seek_table);
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
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);
default:
FLAC__ASSERT(0);
return false;
@@ -527,7 +718,7 @@
{
FLAC__ASSERT(0 != object);
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
- FLAC__ASSERT(object->data.seek_table.num_points > point_num);
+ FLAC__ASSERT(point_num < object->data.seek_table.num_points);
object->data.seek_table.points[point_num] = point;
}
@@ -538,7 +729,7 @@
FLAC__ASSERT(0 != object);
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
- FLAC__ASSERT(object->data.seek_table.num_points >= point_num);
+ FLAC__ASSERT(point_num <= object->data.seek_table.num_points);
if(!FLAC__metadata_object_seektable_resize_points(object, object->data.seek_table.num_points+1))
return false;
@@ -558,7 +749,7 @@
FLAC__ASSERT(0 != object);
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE);
- FLAC__ASSERT(object->data.seek_table.num_points > point_num);
+ FLAC__ASSERT(point_num < object->data.seek_table.num_points);
/* move all points > point_num backward one space */
for(i = point_num; i < object->data.seek_table.num_points-1; i++)
@@ -728,7 +919,7 @@
FLAC__ASSERT(0 != object);
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
- FLAC__ASSERT(object->data.vorbis_comment.num_comments >= comment_num);
+ FLAC__ASSERT(comment_num <= object->data.vorbis_comment.num_comments);
vc = &object->data.vorbis_comment;
@@ -749,7 +940,7 @@
FLAC__ASSERT(0 != object);
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
- FLAC__ASSERT(object->data.vorbis_comment.num_comments > comment_num);
+ FLAC__ASSERT(comment_num < object->data.vorbis_comment.num_comments);
vc = &object->data.vorbis_comment;
@@ -833,3 +1024,184 @@
return ok? (int)matching : -1;
}
+
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices)
+{
+ FLAC__StreamMetadata_CueSheet_Track *track;
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+ FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
+
+ track = &object->data.cue_sheet.tracks[track_num];
+
+ if(0 == track->indices) {
+ FLAC__ASSERT(track->num_indices == 0);
+ if(0 == new_num_indices)
+ return true;
+ else if(0 == (track->indices = cuesheet_track_index_array_new_(new_num_indices)))
+ return false;
+ }
+ else {
+ const unsigned old_size = track->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index);
+ const unsigned new_size = new_num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index);
+
+ FLAC__ASSERT(track->num_indices > 0);
+
+ if(new_size == 0) {
+ free(track->indices);
+ track->indices = 0;
+ }
+ else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)realloc(track->indices, new_size)))
+ return false;
+
+ /* if growing, zero all the lengths/pointers of new elements */
+ if(new_size > old_size)
+ memset(track->indices + track->num_indices, 0, new_size - old_size);
+ }
+
+ track->num_indices = new_num_indices;
+
+ cuesheet_calculate_length_(object);
+ return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index)
+{
+ FLAC__StreamMetadata_CueSheet_Track *track;
+
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+ FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
+ FLAC__ASSERT(index_num <= object->data.cue_sheet.tracks[track_num].num_indices);
+
+ track = &object->data.cue_sheet.tracks[track_num];
+
+ if(!FLAC__metadata_object_cuesheet_track_resize_indices(object, track_num, track->num_indices+1))
+ return false;
+
+ /* move all indices >= index_num forward one space */
+ memmove(&track->indices[index_num+1], &track->indices[index_num], sizeof(FLAC__StreamMetadata_CueSheet_Index)*(track->num_indices-1-index_num));
+
+ track->indices[index_num] = index;
+ cuesheet_calculate_length_(object);
+ return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num)
+{
+ FLAC__StreamMetadata_CueSheet_Track *track;
+
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+ FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
+ FLAC__ASSERT(index_num < object->data.cue_sheet.tracks[track_num].num_indices);
+
+ track = &object->data.cue_sheet.tracks[track_num];
+
+ /* move all indices > index_num backward one space */
+ memmove(&track->indices[index_num], &track->indices[index_num+1], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(track->num_indices-index_num-1));
+
+ FLAC__metadata_object_cuesheet_track_resize_indices(object, track_num, track->num_indices-1);
+ cuesheet_calculate_length_(object);
+ return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks)
+{
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+
+ if(0 == object->data.cue_sheet.tracks) {
+ FLAC__ASSERT(object->data.cue_sheet.num_tracks == 0);
+ if(0 == new_num_tracks)
+ return true;
+ else if(0 == (object->data.cue_sheet.tracks = cuesheet_track_array_new_(new_num_tracks)))
+ return false;
+ }
+ else {
+ const unsigned old_size = object->data.cue_sheet.num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track);
+ const unsigned new_size = new_num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track);
+
+ FLAC__ASSERT(object->data.cue_sheet.num_tracks > 0);
+
+ /* if shrinking, free the truncated entries */
+ if(new_num_tracks < object->data.cue_sheet.num_tracks) {
+ unsigned i;
+ for(i = new_num_tracks; i < object->data.cue_sheet.num_tracks; i++)
+ if(0 != object->data.cue_sheet.tracks[i].indices)
+ free(object->data.cue_sheet.tracks[i].indices);
+ }
+
+ if(new_size == 0) {
+ free(object->data.cue_sheet.tracks);
+ object->data.cue_sheet.tracks = 0;
+ }
+ else if(0 == (object->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)realloc(object->data.cue_sheet.tracks, new_size)))
+ return false;
+
+ /* if growing, zero all the lengths/pointers of new elements */
+ if(new_size > old_size)
+ memset(object->data.cue_sheet.tracks + object->data.cue_sheet.num_tracks, 0, new_size - old_size);
+ }
+
+ object->data.cue_sheet.num_tracks = new_num_tracks;
+
+ cuesheet_calculate_length_(object);
+ return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track track, FLAC__bool copy)
+{
+ return cuesheet_set_track_(object, &object->data.cue_sheet.tracks[track_num], &track, copy);
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track track, FLAC__bool copy)
+{
+ FLAC__StreamMetadata_CueSheet *cs;
+
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+ FLAC__ASSERT(track_num <= object->data.cue_sheet.num_tracks);
+
+ cs = &object->data.cue_sheet;
+
+ if(!FLAC__metadata_object_cuesheet_resize_tracks(object, cs->num_tracks+1))
+ return false;
+
+ /* move all tracks >= track_num forward one space */
+ memmove(&cs->tracks[track_num+1], &cs->tracks[track_num], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(cs->num_tracks-1-track_num));
+ cs->tracks[track_num].num_indices = 0;
+ cs->tracks[track_num].indices = 0;
+
+ return FLAC__metadata_object_cuesheet_set_track(object, track_num, track, copy);
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num)
+{
+ FLAC__StreamMetadata_CueSheet *cs;
+
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+ FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks);
+
+ cs = &object->data.cue_sheet;
+
+ /* free the track at track_num */
+ if(0 != cs->tracks[track_num].indices)
+ free(cs->tracks[track_num].indices);
+
+ /* move all tracks > track_num backward one space */
+ memmove(&cs->tracks[track_num], &cs->tracks[track_num+1], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(cs->num_tracks-track_num-1));
+ cs->tracks[cs->num_tracks-1].num_indices = 0;
+ cs->tracks[cs->num_tracks-1].indices = 0;
+
+ return FLAC__metadata_object_cuesheet_resize_tracks(object, cs->num_tracks-1);
+}
+
+FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_is_legal(const FLAC__StreamMetadata *object, FLAC__bool check_cd_da_subset, const char **violation)
+{
+ FLAC__ASSERT(0 != object);
+ FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
+
+ return FLAC__format_cuesheet_is_legal(&object->data.cue_sheet, check_cd_da_subset, violation);
+}
diff --git a/src/test_libFLAC/metadata_object.c b/src/test_libFLAC/metadata_object.c
index 215f7b3..258d2bf 100644
--- a/src/test_libFLAC/metadata_object.c
+++ b/src/test_libFLAC/metadata_object.c
@@ -183,11 +183,120 @@
vc_calc_len_(block);
}
+static void track_new_(FLAC__StreamMetadata_CueSheet_Track *track, FLAC__uint64 offset, FLAC__byte number, const char *isrc, FLAC__bool data, FLAC__bool pre_em)
+{
+ track->offset = offset;
+ track->number = number;
+ memcpy(track->isrc, isrc, sizeof(track->isrc));
+ track->type = data;
+ track->pre_emphasis = pre_em;
+ track->num_indices = 0;
+ track->indices = 0;
+}
+
+static void track_clone_(FLAC__StreamMetadata_CueSheet_Track *track)
+{
+ if(track->num_indices > 0) {
+ size_t bytes = sizeof(FLAC__StreamMetadata_CueSheet_Index) * track->num_indices;
+ FLAC__StreamMetadata_CueSheet_Index *x = (FLAC__StreamMetadata_CueSheet_Index*)malloc(bytes);
+ FLAC__ASSERT(0 != x);
+ memcpy(x, track->indices, bytes);
+ track->indices = x;
+ }
+}
+
+static void cs_calc_len_(FLAC__StreamMetadata *block)
+{
+ const FLAC__StreamMetadata_CueSheet *cs = &block->data.cue_sheet;
+ unsigned i;
+
+ block->length = (
+ FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN
+ ) / 8;
+ block->length += cs->num_tracks * (
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN
+ ) / 8;
+ for(i = 0; i < cs->num_tracks; i++) {
+ block->length += cs->tracks[i].num_indices * (
+ FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN
+ ) / 8;
+ }
+}
+
+static void cs_resize_(FLAC__StreamMetadata *block, unsigned num)
+{
+ FLAC__StreamMetadata_CueSheet *cs = &block->data.cue_sheet;
+
+ if(cs->num_tracks != 0) {
+ FLAC__ASSERT(0 != cs->tracks);
+ if(num < cs->num_tracks) {
+ unsigned i;
+ for(i = num; i < cs->num_tracks; i++) {
+ if(0 != cs->tracks[i].indices)
+ free(cs->tracks[i].indices);
+ }
+ }
+ }
+ if(num == 0) {
+ if(0 != cs->tracks) {
+ free(cs->tracks);
+ cs->tracks = 0;
+ }
+ }
+ else {
+ cs->tracks = (FLAC__StreamMetadata_CueSheet_Track*)realloc(cs->tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)*num);
+ FLAC__ASSERT(0 != cs->tracks);
+ if(num > cs->num_tracks)
+ memset(cs->tracks+cs->num_tracks, 0, sizeof(FLAC__StreamMetadata_CueSheet_Track)*(num-cs->num_tracks));
+ }
+
+ cs->num_tracks = num;
+ cs_calc_len_(block);
+}
+
+static void cs_set_new_(FLAC__StreamMetadata_CueSheet_Track *track, FLAC__StreamMetadata *block, unsigned pos, FLAC__uint64 offset, FLAC__byte number, const char *isrc, FLAC__bool data, FLAC__bool pre_em)
+{
+ track_new_(track, offset, number, isrc, data, pre_em);
+ block->data.cue_sheet.tracks[pos] = *track;
+ cs_calc_len_(block);
+}
+
+static void cs_insert_new_(FLAC__StreamMetadata_CueSheet_Track *track, FLAC__StreamMetadata *block, unsigned pos, FLAC__uint64 offset, FLAC__byte number, const char *isrc, FLAC__bool data, FLAC__bool pre_em)
+{
+ cs_resize_(block, block->data.cue_sheet.num_tracks+1);
+ memmove(&block->data.cue_sheet.tracks[pos+1], &block->data.cue_sheet.tracks[pos], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(block->data.cue_sheet.num_tracks-1-pos));
+ cs_set_new_(track, block, pos, offset, number, isrc, data, pre_em);
+ cs_calc_len_(block);
+}
+
+static void cs_delete_(FLAC__StreamMetadata *block, unsigned pos)
+{
+ if(0 != block->data.cue_sheet.tracks[pos].indices)
+ free(block->data.cue_sheet.tracks[pos].indices);
+ memmove(&block->data.cue_sheet.tracks[pos], &block->data.cue_sheet.tracks[pos+1], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(block->data.cue_sheet.num_tracks-pos-1));
+ block->data.cue_sheet.tracks[block->data.cue_sheet.num_tracks-1].indices = 0;
+ block->data.cue_sheet.tracks[block->data.cue_sheet.num_tracks-1].num_indices = 0;
+ cs_resize_(block, block->data.cue_sheet.num_tracks-1);
+ cs_calc_len_(block);
+}
+
+
FLAC__bool test_metadata_object()
{
- FLAC__StreamMetadata *block, *blockcopy, *vorbiscomment;
+ FLAC__StreamMetadata *block, *blockcopy, *vorbiscomment, *cuesheet;
FLAC__StreamMetadata_SeekPoint seekpoint_array[8];
FLAC__StreamMetadata_VorbisComment_Entry entry;
+ FLAC__StreamMetadata_CueSheet_Track track;
unsigned i, expected_length, seekpoints;
static FLAC__byte dummydata[4] = { 'a', 'b', 'c', 'd' };
@@ -873,5 +982,269 @@
printf("OK\n");
+ printf("testing CUESHEET\n");
+
+ printf("testing FLAC__metadata_object_new()... ");
+ block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET);
+ if(0 == block) {
+ printf("FAILED, returned NULL\n");
+ return false;
+ }
+ expected_length = (
+ FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN +
+ FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_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()... ");
+ cuesheet = FLAC__metadata_object_clone(block);
+ if(0 == cuesheet) {
+ printf("FAILED, returned NULL\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ cs_resize_(cuesheet, 2);
+ printf("testing FLAC__metadata_object_cuesheet_resize_tracks(grow to %u)...", cuesheet->data.cue_sheet.num_tracks);
+ if(!FLAC__metadata_object_cuesheet_resize_tracks(block, cuesheet->data.cue_sheet.num_tracks)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ cs_resize_(cuesheet, 1);
+ printf("testing FLAC__metadata_object_cuesheet_resize_tracks(shrink to %u)...", cuesheet->data.cue_sheet.num_tracks);
+ if(!FLAC__metadata_object_cuesheet_resize_tracks(block, cuesheet->data.cue_sheet.num_tracks)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ cs_resize_(cuesheet, 0);
+ printf("testing FLAC__metadata_object_cuesheet_resize_tracks(shrink to %u)...", cuesheet->data.cue_sheet.num_tracks);
+ if(!FLAC__metadata_object_cuesheet_resize_tracks(block, cuesheet->data.cue_sheet.num_tracks)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_insert_track(copy) on empty array...");
+ cs_insert_new_(&track, cuesheet, 0, 0, 1, "ABCDE1234567", false, false);
+ if(!FLAC__metadata_object_cuesheet_insert_track(block, 0, track, /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_insert_track(copy) on beginning of non-empty array...");
+ cs_insert_new_(&track, cuesheet, 0, 10, 2, "BBCDE1234567", false, false);
+ if(!FLAC__metadata_object_cuesheet_insert_track(block, 0, track, /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_insert_track(copy) on middle of non-empty array...");
+ cs_insert_new_(&track, cuesheet, 1, 20, 3, "CBCDE1234567", false, false);
+ if(!FLAC__metadata_object_cuesheet_insert_track(block, 1, track, /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_insert_track(copy) on end of non-empty array...");
+ cs_insert_new_(&track, cuesheet, 3, 30, 4, "DBCDE1234567", false, false);
+ if(!FLAC__metadata_object_cuesheet_insert_track(block, 3, track, /*copy=*/true)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, 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(!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_cuesheet_delete_track() on middle of array...");
+ cs_delete_(cuesheet, 2);
+ if(!FLAC__metadata_object_cuesheet_delete_track(block, 2)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_delete_track() on end of array...");
+ cs_delete_(cuesheet, 2);
+ if(!FLAC__metadata_object_cuesheet_delete_track(block, 2)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_delete_track() on beginning of array...");
+ cs_delete_(cuesheet, 0);
+ if(!FLAC__metadata_object_cuesheet_delete_track(block, 0)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_set_track(copy)...");
+ cs_set_new_(&track, cuesheet, 0, 40, 5, "EBCDE1234567", false, false);
+ FLAC__metadata_object_cuesheet_set_track(block, 0, track, /*copy=*/true);
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ /*@@@@ track index function tests here*/
+
+ printf("testing FLAC__metadata_object_delete()... ");
+ FLAC__metadata_object_delete(cuesheet);
+ FLAC__metadata_object_delete(block);
+ printf("OK\n");
+
+
+ printf("testing FLAC__metadata_object_new()... ");
+ block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET);
+ if(0 == block) {
+ printf("FAILED, returned NULL\n");
+ return false;
+ }
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_clone()... ");
+ cuesheet = FLAC__metadata_object_clone(block);
+ if(0 == cuesheet) {
+ printf("FAILED, returned NULL\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_insert_track(own) on empty array...");
+ cs_insert_new_(&track, cuesheet, 0, 60, 7, "GBCDE1234567", false, false);
+ track_clone_(&track);
+ if(!FLAC__metadata_object_cuesheet_insert_track(block, 0, track, /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_insert_track(own) on beginning of non-empty array...");
+ cs_insert_new_(&track, cuesheet, 0, 70, 8, "HBCDE1234567", false, false);
+ track_clone_(&track);
+ if(!FLAC__metadata_object_cuesheet_insert_track(block, 0, track, /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_insert_track(own) on middle of non-empty array...");
+ cs_insert_new_(&track, cuesheet, 1, 80, 9, "IBCDE1234567", false, false);
+ track_clone_(&track);
+ if(!FLAC__metadata_object_cuesheet_insert_track(block, 1, track, /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_insert_track(own) on end of non-empty array...");
+ cs_insert_new_(&track, cuesheet, 3, 90, 10, "JBCDE1234567", false, false);
+ track_clone_(&track);
+ if(!FLAC__metadata_object_cuesheet_insert_track(block, 3, track, /*copy=*/false)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_delete_track() on middle of array...");
+ cs_delete_(cuesheet, 2);
+ if(!FLAC__metadata_object_cuesheet_delete_track(block, 2)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_delete_track() on end of array...");
+ cs_delete_(cuesheet, 2);
+ if(!FLAC__metadata_object_cuesheet_delete_track(block, 2)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_delete_track() on beginning of array...");
+ cs_delete_(cuesheet, 0);
+ if(!FLAC__metadata_object_cuesheet_delete_track(block, 0)) {
+ printf("FAILED, returned false\n");
+ return false;
+ }
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_cuesheet_set_track(own)...");
+ cs_set_new_(&track, cuesheet, 0, 100, 11, "KBCDE1234567", false, false);
+ track_clone_(&track);
+ FLAC__metadata_object_cuesheet_set_track(block, 0, track, /*copy=*/false);
+ if(!compare_block_(cuesheet, block))
+ return false;
+ printf("OK\n");
+
+ printf("testing FLAC__metadata_object_delete()... ");
+ FLAC__metadata_object_delete(cuesheet);
+ FLAC__metadata_object_delete(block);
+ printf("OK\n");
+
+
return true;
}
diff --git a/src/test_libFLAC/metadata_utils.c b/src/test_libFLAC/metadata_utils.c
index eadd581..ab77755 100644
--- a/src/test_libFLAC/metadata_utils.c
+++ b/src/test_libFLAC/metadata_utils.c
@@ -215,6 +215,69 @@
return true;
}
+FLAC__bool compare_block_data_cuesheet_(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy)
+{
+ unsigned i, j;
+
+ if(0 != strcmp(blockcopy->media_catalog_number, block->media_catalog_number)) {
+ printf("FAILED, media_catalog_number mismatch, expected %s, got %s\n", block->media_catalog_number, blockcopy->media_catalog_number);
+ return false;
+ }
+ if(blockcopy->lead_in != block->lead_in) {
+ printf("FAILED, lead_in mismatch, expected %llu, got %llu\n", block->lead_in, blockcopy->lead_in);
+ return false;
+ }
+ if(blockcopy->num_tracks != block->num_tracks) {
+ printf("FAILED, num_tracks mismatch, expected %u, got %u\n", block->num_tracks, blockcopy->num_tracks);
+ return false;
+ }
+ for(i = 0; i < block->num_tracks; i++) {
+ if(blockcopy->tracks[i].offset != block->tracks[i].offset) {
+ printf("FAILED, tracks[%u].offset mismatch, expected %llu, got %llu\n", i, block->tracks[i].offset, blockcopy->tracks[i].offset);
+ return false;
+ }
+ if(blockcopy->tracks[i].number != block->tracks[i].number) {
+ printf("FAILED, tracks[%u].number mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].number, (unsigned)blockcopy->tracks[i].number);
+ return false;
+ }
+ if(0 != strcmp(blockcopy->tracks[i].isrc, block->tracks[i].isrc)) {
+ printf("FAILED, tracks[%u].number mismatch, expected %s, got %s\n", i, block->tracks[i].isrc, blockcopy->tracks[i].isrc);
+ return false;
+ }
+ if(blockcopy->tracks[i].type != block->tracks[i].type) {
+ printf("FAILED, tracks[%u].type mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].type, (unsigned)blockcopy->tracks[i].type);
+ return false;
+ }
+ if(blockcopy->tracks[i].pre_emphasis != block->tracks[i].pre_emphasis) {
+ printf("FAILED, tracks[%u].pre_emphasis mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].pre_emphasis, (unsigned)blockcopy->tracks[i].pre_emphasis);
+ return false;
+ }
+ if(blockcopy->tracks[i].num_indices != block->tracks[i].num_indices) {
+ printf("FAILED, tracks[%u].num_indices mismatch, expected %u, got %u\n", i, (unsigned)block->tracks[i].num_indices, (unsigned)blockcopy->tracks[i].num_indices);
+ return false;
+ }
+ if(0 == block->tracks[i].indices || 0 == blockcopy->tracks[i].indices) {
+ if(block->tracks[i].indices != blockcopy->tracks[i].indices) {
+ printf("FAILED, tracks[%u].indices mismatch\n", i);
+ return false;
+ }
+ }
+ else {
+ for(j = 0; j < block->tracks[i].num_indices; j++) {
+ if(blockcopy->tracks[i].indices[j].offset != block->tracks[i].indices[j].offset) {
+ printf("FAILED, tracks[%u].indices[%u].offset mismatch, expected %llu, got %llu\n", i, j, block->tracks[i].indices[j].offset, blockcopy->tracks[i].indices[j].offset);
+ return false;
+ }
+ if(blockcopy->tracks[i].indices[j].number != block->tracks[i].indices[j].number) {
+ printf("FAILED, tracks[%u].indices[%u].number mismatch, expected %u, got %u\n", i, j, (unsigned)block->tracks[i].indices[j].number, (unsigned)blockcopy->tracks[i].indices[j].number);
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
FLAC__bool compare_block_(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy)
{
if(blockcopy->type != block->type) {
@@ -240,6 +303,8 @@
return compare_block_data_seektable_(&block->data.seek_table, &blockcopy->data.seek_table);
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
return compare_block_data_vorbiscomment_(&block->data.vorbis_comment, &blockcopy->data.vorbis_comment);
+ case FLAC__METADATA_TYPE_CUESHEET:
+ return compare_block_data_cuesheet_(&block->data.cue_sheet, &blockcopy->data.cue_sheet);
default:
printf("FAILED, invalid block type %u\n", (unsigned)block->type);
return false;
diff --git a/src/test_libFLAC/metadata_utils.h b/src/test_libFLAC/metadata_utils.h
index 03dca57..3fb8fe6 100644
--- a/src/test_libFLAC/metadata_utils.h
+++ b/src/test_libFLAC/metadata_utils.h
@@ -38,6 +38,8 @@
FLAC__bool compare_block_data_vorbiscomment_(const FLAC__StreamMetadata_VorbisComment *block, const FLAC__StreamMetadata_VorbisComment *blockcopy);
+FLAC__bool compare_block_data_cuesheet_(const FLAC__StreamMetadata_CueSheet *block, const FLAC__StreamMetadata_CueSheet *blockcopy);
+
FLAC__bool compare_block_(const FLAC__StreamMetadata *block, const FLAC__StreamMetadata *blockcopy);
#endif