add FLAC__metadata_get_cuesheet() and FLAC__metadata_object_cuesheet_calculate_cddb_id()

This commit is contained in:
Josh Coalson
2006-04-10 05:37:34 +00:00
parent 91018c8ef7
commit 7cfac0b146
8 changed files with 303 additions and 118 deletions

View File

@@ -153,113 +153,91 @@ static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecode
typedef struct {
FLAC__bool got_error;
FLAC__bool got_object;
FLAC__StreamMetadata *object;
} level0_client_data;
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
static FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type)
{
level0_client_data cd;
FLAC__FileDecoder *decoder;
FLAC__ASSERT(0 != filename);
cd.got_error = false;
cd.object = 0;
decoder = FLAC__file_decoder_new();
if(0 == decoder)
return 0;
FLAC__file_decoder_set_md5_checking(decoder, false);
FLAC__file_decoder_set_filename(decoder, filename);
FLAC__file_decoder_set_metadata_ignore_all(decoder);
FLAC__file_decoder_set_metadata_respond(decoder, type);
FLAC__file_decoder_set_write_callback(decoder, write_callback_);
FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
FLAC__file_decoder_set_error_callback(decoder, error_callback_);
FLAC__file_decoder_set_client_data(decoder, &cd);
if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK || cd.got_error) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
return 0;
}
if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
if(0 != cd.object)
FLAC__metadata_object_delete(cd.object);
return 0;
}
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
return cd.object;
}
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
{
FLAC__StreamMetadata *object;
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != streaminfo);
decoder = FLAC__file_decoder_new();
object = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_STREAMINFO);
if(0 == decoder)
return false;
cd.got_error = false;
cd.got_object = false;
cd.object = 0;
FLAC__file_decoder_set_md5_checking(decoder, false);
FLAC__file_decoder_set_filename(decoder, filename);
FLAC__file_decoder_set_metadata_ignore_all(decoder);
FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
FLAC__file_decoder_set_write_callback(decoder, write_callback_);
FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
FLAC__file_decoder_set_error_callback(decoder, error_callback_);
FLAC__file_decoder_set_client_data(decoder, &cd);
if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK || cd.got_error) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
return false;
}
if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
if(0 != cd.object)
FLAC__metadata_object_delete(cd.object);
return false;
}
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
if(cd.got_object) {
if (object) {
/* can just copy the contents since STREAMINFO has no internal structure */
*streaminfo = *(cd.object);
*streaminfo = *object;
FLAC__metadata_object_delete(object);
return true;
}
else {
return false;
}
if(0 != cd.object)
FLAC__metadata_object_delete(cd.object);
return cd.got_object;
}
FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags)
{
level0_client_data cd;
FLAC__FileDecoder *decoder;
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != tags);
decoder = FLAC__file_decoder_new();
*tags = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_VORBIS_COMMENT);
if(0 == decoder)
return false;
return 0 != *tags;
}
*tags = 0;
FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet)
{
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != cuesheet);
cd.got_error = false;
cd.got_object = false;
cd.object = 0;
*cuesheet = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_CUESHEET);
FLAC__file_decoder_set_md5_checking(decoder, false);
FLAC__file_decoder_set_filename(decoder, filename);
FLAC__file_decoder_set_metadata_ignore_all(decoder);
FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
FLAC__file_decoder_set_write_callback(decoder, write_callback_);
FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
FLAC__file_decoder_set_error_callback(decoder, error_callback_);
FLAC__file_decoder_set_client_data(decoder, &cd);
if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK || cd.got_error) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
return false;
}
if(!FLAC__file_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
if(0 != cd.object)
FLAC__metadata_object_delete(cd.object);
return false;
}
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
if(cd.got_object)
*tags = cd.object;
return cd.got_object;
return 0 != *cuesheet;
}
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
@@ -278,11 +256,9 @@ void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMeta
* we assume we only get here when the one metadata block we were
* looking for was passed to us
*/
if(!cd->got_object) {
if(!cd->got_error && 0 == cd->object) {
if(0 == (cd->object = FLAC__metadata_object_clone(metadata)))
cd->got_error = true;
else
cd->got_object = true;
}
}

View File

@@ -1470,3 +1470,49 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_is_legal(const FLAC__StreamMe
return FLAC__format_cuesheet_is_legal(&object->data.cue_sheet, check_cd_da_subset, violation);
}
static FLAC__uint64 get_index_01_offset_(const FLAC__StreamMetadata_CueSheet *cs, unsigned track)
{
if (track >= (cs->num_tracks-1) || cs->tracks[track].num_indices < 1)
return 0;
else if (cs->tracks[track].indices[0].number == 1)
return cs->tracks[track].indices[0].offset + cs->tracks[track].offset + cs->lead_in;
else if (cs->tracks[track].num_indices < 2)
return 0;
else if (cs->tracks[track].indices[1].number == 1)
return cs->tracks[track].indices[1].offset + cs->tracks[track].offset + cs->lead_in;
else
return 0;
}
static FLAC__uint32 cddb_add_digits_(FLAC__uint32 x)
{
FLAC__uint32 n = 0;
while (x) {
n += (x%10);
x /= 10;
}
return n;
}
FLAC_API FLAC__uint32 FLAC__metadata_object_cuesheet_calculate_cddb_id(const FLAC__StreamMetadata *object)
{
const FLAC__StreamMetadata_CueSheet *cs;
FLAC__ASSERT(0 != object);
FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET);
cs = &object->data.cue_sheet;
if (cs->num_tracks < 2) /* need at least one real track and the lead-out track */
return 0;
{
FLAC__uint32 i, length, sum = 0;
for (i = 0; i < (cs->num_tracks-1); i++) /* -1 to avoid counting the lead-out */
sum += cddb_add_digits_((FLAC__uint32)(get_index_01_offset_(cs, i) / 44100));
length = (FLAC__uint32)((cs->tracks[cs->num_tracks-1].offset+cs->lead_in) / 44100) - (FLAC__uint32)(get_index_01_offset_(cs, 0) / 44100);
return (sum % 0xFF) << 24 | length << 8 | (FLAC__uint32)(cs->num_tracks-1);
}
}