mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
Allow MM:SS:FF and MM:SS.SS time formats in non-CD-DA cuesheets (SF#1947353, SF#2182432: https://sourceforge.net/tracker2/?func=detail&aid=1947353&group_id=13478&atid=363478 https://sourceforge.net/tracker2/index.php?func=detail&aid=2182432&group_id=13478&atid=113478)
This commit is contained in:
@@ -76,10 +76,11 @@ static FLAC__int64 local__parse_int64_(const char *s)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* accept '[0-9]+:[0-9][0-9]?:[0-9][0-9]?', but max second of 59 and max frame of 74, e.g. 0:0:0, 123:45:67
|
||||
/* accept minute:second:frame syntax of '[0-9]+:[0-9][0-9]?:[0-9][0-9]?', but max second of 59 and max frame of 74, e.g. 0:0:0, 123:45:67
|
||||
* return sample number or <0 for error
|
||||
* WATCHOUT: if sample rate is not evenly divisible by 75, the resulting sample number will be approximate
|
||||
*/
|
||||
static FLAC__int64 local__parse_msf_(const char *s)
|
||||
static FLAC__int64 local__parse_msf_(const char *s, unsigned sample_rate)
|
||||
{
|
||||
FLAC__int64 ret, field;
|
||||
char c;
|
||||
@@ -96,7 +97,7 @@ static FLAC__int64 local__parse_msf_(const char *s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = field * 60 * 44100;
|
||||
ret = field * 60 * sample_rate;
|
||||
|
||||
c = *s++;
|
||||
if(c >= '0' && c <= '9')
|
||||
@@ -117,7 +118,7 @@ static FLAC__int64 local__parse_msf_(const char *s)
|
||||
if(field >= 60)
|
||||
return -1;
|
||||
|
||||
ret += field * 44100;
|
||||
ret += field * sample_rate;
|
||||
|
||||
c = *s++;
|
||||
if(c >= '0' && c <= '9')
|
||||
@@ -139,7 +140,45 @@ static FLAC__int64 local__parse_msf_(const char *s)
|
||||
if(field >= 75)
|
||||
return -1;
|
||||
|
||||
ret += field * (44100 / 75);
|
||||
ret += field * (sample_rate / 75);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* accept minute:second syntax of '[0-9]+:[0-9][0-9]?{,.[0-9]+}', but second < 60, e.g. 0:0.0, 3:5, 15:31.731
|
||||
* return sample number or <0 for error
|
||||
* WATCHOUT: depending on the sample rate, the resulting sample number may be approximate with fractional seconds
|
||||
*/
|
||||
static FLAC__int64 local__parse_ms_(const char *s, unsigned sample_rate)
|
||||
{
|
||||
FLAC__int64 ret, field;
|
||||
double x;
|
||||
char c, *end;
|
||||
|
||||
c = *s++;
|
||||
if(c >= '0' && c <= '9')
|
||||
field = (c - '0');
|
||||
else
|
||||
return -1;
|
||||
while(':' != (c = *s++)) {
|
||||
if(c >= '0' && c <= '9')
|
||||
field = field * 10 + (c - '0');
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = field * 60 * sample_rate;
|
||||
|
||||
s++; /* skip the ':' */
|
||||
if(strspn(s, "0123456789.") != strlen(s))
|
||||
return -1;
|
||||
x = strtod(s, &end);
|
||||
if(*end || end == s)
|
||||
return -1;
|
||||
if(x < 0.0 || x >= 60.0)
|
||||
return -1;
|
||||
|
||||
ret += (FLAC__int64)(x * sample_rate);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -198,7 +237,7 @@ static char *local__get_field_(char **s, FLAC__bool allow_quotes)
|
||||
return p;
|
||||
}
|
||||
|
||||
static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__StreamMetadata *cuesheet, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
|
||||
static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__StreamMetadata *cuesheet, unsigned sample_rate, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
|
||||
{
|
||||
#if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
|
||||
#define FLAC__STRCASECMP stricmp
|
||||
@@ -212,6 +251,13 @@ static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message,
|
||||
FLAC__bool disc_has_catalog = false, track_has_flags = false, track_has_isrc = false, has_forced_leadout = false;
|
||||
FLAC__StreamMetadata_CueSheet *cs = &cuesheet->data.cue_sheet;
|
||||
|
||||
FLAC__ASSERT(!is_cdda || sample_rate == 44100);
|
||||
/* double protection */
|
||||
if(is_cdda && sample_rate != 44100) {
|
||||
*error_message = "CD-DA cuesheet only allowed with 44.1kHz sample rate";
|
||||
return false;
|
||||
}
|
||||
|
||||
cs->lead_in = is_cdda? 2 * 44100 /* The default lead-in size for CD-DA */ : 0;
|
||||
cs->is_cd = is_cdda;
|
||||
|
||||
@@ -302,18 +348,28 @@ static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message,
|
||||
*error_message = "INDEX is missing an offset after the index number";
|
||||
return false;
|
||||
}
|
||||
xx = local__parse_msf_(field);
|
||||
/* first parse as minute:second:frame format */
|
||||
xx = local__parse_msf_(field, sample_rate);
|
||||
if(xx < 0) {
|
||||
/* CD-DA must use only MM:SS:FF format */
|
||||
if(is_cdda) {
|
||||
*error_message = "illegal INDEX offset (not of the form MM:SS:FF)";
|
||||
return false;
|
||||
}
|
||||
xx = local__parse_int64_(field);
|
||||
/* as an extension for non-CD-DA we allow MM:SS.SS or raw sample number */
|
||||
xx = local__parse_ms_(field, sample_rate);
|
||||
if(xx < 0) {
|
||||
*error_message = "illegal INDEX offset";
|
||||
return false;
|
||||
xx = local__parse_int64_(field);
|
||||
if(xx < 0) {
|
||||
*error_message = "illegal INDEX offset";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sample_rate % 75) {
|
||||
*error_message = "illegal INDEX offset (MM:SS:FF form not allowed if sample rate is not a multiple of 75)";
|
||||
return false;
|
||||
}
|
||||
if(is_cdda && cs->num_tracks == 1 && cs->tracks[0].num_indices == 0 && xx != 0) {
|
||||
*error_message = "first INDEX of first TRACK must have an offset of 00:00:00";
|
||||
return false;
|
||||
@@ -533,7 +589,7 @@ static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message,
|
||||
#undef FLAC__STRCASECMP
|
||||
}
|
||||
|
||||
FLAC__StreamMetadata *grabbag__cuesheet_parse(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
|
||||
FLAC__StreamMetadata *grabbag__cuesheet_parse(FILE *file, const char **error_message, unsigned *last_line_read, unsigned sample_rate, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
|
||||
{
|
||||
FLAC__StreamMetadata *cuesheet;
|
||||
|
||||
@@ -549,7 +605,7 @@ FLAC__StreamMetadata *grabbag__cuesheet_parse(FILE *file, const char **error_mes
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!local__cuesheet_parse_(file, error_message, last_line_read, cuesheet, is_cdda, lead_out_offset)) {
|
||||
if(!local__cuesheet_parse_(file, error_message, last_line_read, cuesheet, sample_rate, is_cdda, lead_out_offset)) {
|
||||
FLAC__metadata_object_delete(cuesheet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user