From: Ulrich Klauer Date: Thu, 11 Apr 2013 20:07:49 +0000 (+0200) Subject: Use C locale when reading ReplayGain tag X-Git-Tag: 1.3.0~22 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=aa285f3ac18a9825e9081af87545c8406e10f2d1;p=platform%2Fupstream%2Fflac.git Use C locale when reading ReplayGain tag When a locale is in effect that does not use the point as the decimal mark (e.g., sv_SE or de_DE, which use a comma) and a ReplayGain tag is read for --apply-replaygain-which-is-not-lossless, the gain value was misinterpreted (e.g., "-2.29" truncated to "-2"). This is fixed by resetting the locale to "C" temporarily, based on Josh Coalson's fix of the dual case (writing ReplayGain tag) in commit cda02d3. Patch by hhaamu@gmail.com, taken from the Debian patch tracker for flac 1.2.1-6 (13_replaygain_c_locale.patch). http://sourceforge.net/p/flac/bugs/380/ Signed-off-by: Erik de Castro Lopo --- diff --git a/src/share/grabbag/replaygain.c b/src/share/grabbag/replaygain.c index 43f1be0..347319f 100644 --- a/src/share/grabbag/replaygain.c +++ b/src/share/grabbag/replaygain.c @@ -606,6 +606,8 @@ static FLAC__bool parse_double_(const FLAC__StreamMetadata_VorbisComment_Entry * FLAC__bool grabbag__replaygain_load_from_vorbiscomment(const FLAC__StreamMetadata *block, FLAC__bool album_mode, FLAC__bool strict, double *reference, double *gain, double *peak) { int reference_offset, gain_offset, peak_offset; + char *saved_locale; + FLAC__bool res = true; FLAC__ASSERT(0 != block); FLAC__ASSERT(0 != reference); @@ -618,20 +620,36 @@ FLAC__bool grabbag__replaygain_load_from_vorbiscomment(const FLAC__StreamMetadat */ *reference = ReplayGainReferenceLoudness; + /* + * We need to save the old locale and switch to "C" because the locale + * influences the formatting of %f and we want it a certain way. + */ + saved_locale = strdup(setlocale(LC_ALL, 0)); + if (0 == saved_locale) + return false; + setlocale(LC_ALL, "C"); + if(0 <= (reference_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS))) (void)parse_double_(block->data.vorbis_comment.comments + reference_offset, reference); if(0 > (gain_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)(album_mode? GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN : GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN)))) - return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); + res = false; if(0 > (peak_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)(album_mode? GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK : GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK)))) - return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); + res = false; - if(!parse_double_(block->data.vorbis_comment.comments + gain_offset, gain)) - return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); - if(!parse_double_(block->data.vorbis_comment.comments + peak_offset, peak)) - return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); + if(res && !parse_double_(block->data.vorbis_comment.comments + gain_offset, gain)) + res = false; + if(res && !parse_double_(block->data.vorbis_comment.comments + peak_offset, peak)) + res = false; - return true; + setlocale(LC_ALL, saved_locale); + free(saved_locale); + + /* something failed; retry with strict */ + if (!res && !strict) + res = grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); + + return res; } double grabbag__replaygain_compute_scale_factor(double peak, double gain, double preamp, FLAC__bool prevent_clipping)