implement new CUESHEET metadata block

This commit is contained in:
Josh Coalson 2002-11-14 05:00:24 +00:00
parent 5f34956e5b
commit 8e9c4519e7
7 changed files with 1072 additions and 26 deletions

View File

@ -449,16 +449,19 @@ typedef enum {
/**< <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 @@ typedef struct {
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 @@ typedef struct {
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 FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_S
*/
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

View File

@ -1231,7 +1231,7 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__Str
*/
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_delete_comment(FLAC__Str
*/
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 FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC
*/
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_find_entry_from(const FLAC__Str
*/
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_entry_matching(FLAC__Str
*/
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

View File

@ -67,6 +67,22 @@ FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = 0xffff
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 @@ FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *se
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

View File

@ -66,6 +66,23 @@ static FLAC__bool copy_vcentry_(FLAC__StreamMetadata_VorbisComment_Entry *to, co
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 @@ static FLAC__StreamMetadata_VorbisComment_Entry *vorbiscomment_entry_array_copy_
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 @@ static FLAC__bool vorbiscomment_set_entry_(FLAC__StreamMetadata *object, FLAC__S
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 @@ FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_new(FLAC__MetadataType type
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 @@ FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_clone(const FLAC__StreamMet
}
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 @@ void FLAC__metadata_object_delete_data(FLAC__StreamMetadata *object)
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 @@ static FLAC__bool compare_block_data_vorbiscomment_(const FLAC__StreamMetadata_V
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 @@ FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *b
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_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *ob
{
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_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMet
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_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMet
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_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__Str
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_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__Str
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 @@ FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__S
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);
}

View File

@ -183,11 +183,120 @@ static void vc_delete_(FLAC__StreamMetadata *block, unsigned pos)
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 @@ FLAC__bool test_metadata_object()
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;
}

View File

@ -215,6 +215,69 @@ FLAC__bool compare_block_data_vorbiscomment_(const FLAC__StreamMetadata_VorbisCo
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 @@ FLAC__bool compare_block_(const FLAC__StreamMetadata *block, const FLAC__StreamM
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;

View File

@ -38,6 +38,8 @@ FLAC__bool compare_block_data_seektable_(const FLAC__StreamMetadata_SeekTable *b
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