From a6aaeafdca41f61d86f1495be28cfae259051202 Mon Sep 17 00:00:00 2001 From: Dzmitry Neviadomski Date: Sun, 7 Feb 2021 06:50:28 +0300 Subject: [PATCH] Re-apply patch for replay gain support --- .../TagLib/taglib/taglib/ape/apetag.cpp | 60 ++++++++++++++ Frameworks/TagLib/taglib/taglib/ape/apetag.h | 8 ++ .../TagLib/taglib/taglib/asf/asftag.cpp | 36 +++++++++ Frameworks/TagLib/taglib/taglib/asf/asftag.h | 10 +++ .../TagLib/taglib/taglib/mod/modtag.cpp | 36 +++++++++ Frameworks/TagLib/taglib/taglib/mod/modtag.h | 40 ++++++++++ .../TagLib/taglib/taglib/mp4/mp4tag.cpp | 44 ++++++++++ Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h | 8 ++ .../taglib/taglib/mpeg/id3v1/id3v1tag.cpp | 36 +++++++++ .../taglib/taglib/mpeg/id3v1/id3v1tag.h | 8 ++ .../taglib/taglib/mpeg/id3v2/id3v2tag.cpp | 80 +++++++++++++++++++ .../taglib/taglib/mpeg/id3v2/id3v2tag.h | 12 +++ .../TagLib/taglib/taglib/ogg/xiphcomment.cpp | 60 ++++++++++++++ .../TagLib/taglib/taglib/ogg/xiphcomment.h | 8 ++ .../TagLib/taglib/taglib/riff/wav/infotag.cpp | 36 +++++++++ .../TagLib/taglib/taglib/riff/wav/infotag.h | 8 ++ Frameworks/TagLib/taglib/taglib/tag.h | 48 +++++++++++ Frameworks/TagLib/taglib/taglib/tagunion.cpp | 49 ++++++++++++ Frameworks/TagLib/taglib/taglib/tagunion.h | 8 ++ .../TagLib/taglib/taglib/toolkit/tstring.cpp | 27 +++++++ .../TagLib/taglib/taglib/toolkit/tstring.h | 23 ++++++ Plugins/TagLib/TagLibMetadataReader.m | 22 +++-- 22 files changed, 655 insertions(+), 12 deletions(-) diff --git a/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp b/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp index a2bdaeed9..b8dfc2b96 100644 --- a/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp +++ b/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp @@ -165,6 +165,34 @@ unsigned int APE::Tag::track() const return d->itemListMap["TRACK"].toString().toInt(); } +float APE::Tag::rgAlbumGain() const +{ + if (d->itemListMap["REPLAYGAIN_ALBUM_GAIN"].isEmpty()) + return 0; + return d->itemListMap["REPLAYGAIN_ALBUM_GAIN"].toString().toFloat(); +} + +float APE::Tag::rgAlbumPeak() const +{ + if (d->itemListMap["REPLAYGAIN_ALBUM_PEAK"].isEmpty()) + return 0; + return d->itemListMap["REPLAYGAIN_ALBUM_PEAK"].toString().toFloat(); +} + +float APE::Tag::rgTrackGain() const +{ + if (d->itemListMap["REPLAYGAIN_TRACK_GAIN"].isEmpty()) + return 0; + return d->itemListMap["REPLAYGAIN_TRACK_GAIN"].toString().toFloat(); +} + +float APE::Tag::rgTrackPeak() const +{ + if (d->itemListMap["REPLAYGAIN_TRACK_PEAK"].isEmpty()) + return 0; + return d->itemListMap["REPLAYGAIN_TRACK_PEAK"].toString().toFloat(); +} + void APE::Tag::setTitle(const String &s) { addValue("TITLE", s, true); @@ -206,6 +234,38 @@ void APE::Tag::setTrack(unsigned int i) addValue("TRACK", String::number(i), true); } +void APE::Tag::setRGAlbumGain(float f) +{ + if (f == 0) + removeItem("REPLAYGAIN_ALBUM_GAIN"); + else + addValue("REPLAYGAIN_ALBUM_GAIN", String::number(f) + " dB", true); +} + +void APE::Tag::setRGAlbumPeak(float f) +{ + if (f == 0) + removeItem("REPLAYGAIN_ALBUM_PEAK"); + else + addValue("REPLAYGAIN_ALBUM_PEAK", String::number(f), true); +} + +void APE::Tag::setRGTrackGain(float f) +{ + if (f == 0) + removeItem("REPLAYGAIN_TRACK_GAIN"); + else + addValue("REPLAYGAIN_TRACK_GAIN", String::number(f) + " dB", true); +} + +void APE::Tag::setRGTrackPeak(float f) +{ + if (f == 0) + removeItem("REPLAYGAIN_TRACK_PEAK"); + else + addValue("REPLAYGAIN_TRACK_PEAK", String::number(f), true); +} + namespace { // conversions of tag keys between what we use in PropertyMap and what's usual diff --git a/Frameworks/TagLib/taglib/taglib/ape/apetag.h b/Frameworks/TagLib/taglib/taglib/ape/apetag.h index f4d4fba64..40ed38699 100644 --- a/Frameworks/TagLib/taglib/taglib/ape/apetag.h +++ b/Frameworks/TagLib/taglib/taglib/ape/apetag.h @@ -94,6 +94,10 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual float rgAlbumGain() const; + virtual float rgAlbumPeak() const; + virtual float rgTrackGain() const; + virtual float rgTrackPeak() const; virtual void setTitle(const String &s); virtual void setArtist(const String &s); @@ -102,6 +106,10 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setRGAlbumGain(float f); + virtual void setRGAlbumPeak(float f); + virtual void setRGTrackGain(float f); + virtual void setRGTrackPeak(float f); /*! * Implements the unified tag dictionary interface -- export function. diff --git a/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp b/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp index 935db046c..063374e7f 100644 --- a/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp +++ b/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp @@ -110,6 +110,26 @@ String ASF::Tag::genre() const return String(); } +float ASF::Tag::rgAlbumGain() const +{ + return 0; +} + +float ASF::Tag::rgAlbumPeak() const +{ + return 0; +} + +float ASF::Tag::rgTrackGain() const +{ + return 0; +} + +float ASF::Tag::rgTrackPeak() const +{ + return 0; +} + void ASF::Tag::setTitle(const String &value) { d->title = value; @@ -155,6 +175,22 @@ void ASF::Tag::setTrack(unsigned int value) setAttribute("WM/TrackNumber", String::number(value)); } +void ASF::Tag::setRGAlbumGain(float) +{ +} + +void ASF::Tag::setRGAlbumPeak(float) +{ +} + +void ASF::Tag::setRGTrackGain(float) +{ +} + +void ASF::Tag::setRGTrackPeak(float) +{ +} + ASF::AttributeListMap& ASF::Tag::attributeListMap() { return d->attributeListMap; diff --git a/Frameworks/TagLib/taglib/taglib/asf/asftag.h b/Frameworks/TagLib/taglib/taglib/asf/asftag.h index bbd98212f..5363c5db4 100644 --- a/Frameworks/TagLib/taglib/taglib/asf/asftag.h +++ b/Frameworks/TagLib/taglib/taglib/asf/asftag.h @@ -98,6 +98,11 @@ namespace TagLib { */ virtual unsigned int track() const; + virtual float rgAlbumGain() const; + virtual float rgAlbumPeak() const; + virtual float rgTrackGain() const; + virtual float rgTrackPeak() const; + /*! * Sets the title to \a s. */ @@ -144,6 +149,11 @@ namespace TagLib { */ virtual void setTrack(unsigned int i); + virtual void setRGAlbumGain(float f); + virtual void setRGAlbumPeak(float f); + virtual void setRGTrackGain(float f); + virtual void setRGTrackPeak(float f); + /*! * Returns true if the tag does not contain any data. This should be * reimplemented in subclasses that provide more than the basic tagging diff --git a/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp b/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp index 0e8d03719..6737d0955 100644 --- a/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp @@ -89,6 +89,26 @@ unsigned int Mod::Tag::track() const return 0; } +float Mod::Tag::rgAlbumGain() const +{ + return 0; +} + +float Mod::Tag::rgAlbumPeak() const +{ + return 0; +} + +float Mod::Tag::rgTrackGain() const +{ + return 0; +} + +float Mod::Tag::rgTrackPeak() const +{ + return 0; +} + String Mod::Tag::trackerName() const { return d->trackerName; @@ -124,6 +144,22 @@ void Mod::Tag::setTrack(unsigned int) { } +void Mod::Tag::setRGAlbumGain(float) +{ +} + +void Mod::Tag::setRGAlbumPeak(float) +{ +} + +void Mod::Tag::setRGTrackGain(float) +{ +} + +void Mod::Tag::setRGTrackPeak(float) +{ +} + void Mod::Tag::setTrackerName(const String &trackerName) { d->trackerName = trackerName; diff --git a/Frameworks/TagLib/taglib/taglib/mod/modtag.h b/Frameworks/TagLib/taglib/taglib/mod/modtag.h index dee066171..4b2d44b45 100644 --- a/Frameworks/TagLib/taglib/taglib/mod/modtag.h +++ b/Frameworks/TagLib/taglib/taglib/mod/modtag.h @@ -88,6 +88,26 @@ namespace TagLib { */ virtual unsigned int track() const; + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual float rgAlbumGain() const; + + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual float rgAlbumPeak() const; + + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual float rgTrackGain() const; + + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual float rgTrackPeak() const; + /*! * Returns the name of the tracker used to create/edit the module file. * Only XM files store this tag to the file as such, for other formats @@ -151,6 +171,26 @@ namespace TagLib { */ virtual void setTrack(unsigned int track); + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setRGAlbumGain(float f); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setRGAlbumPeak(float f); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setRGTrackGain(float f); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setRGTrackPeak(float f); + /*! * Sets the tracker name to \a trackerName. If \a trackerName is * String::null then this value will be cleared. diff --git a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp index a99b71016..89b770fe2 100644 --- a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp @@ -772,6 +772,30 @@ MP4::Tag::track() const return 0; } +float +MP4::Tag::rgAlbumGain() const +{ + return 0; +} + +float +MP4::Tag::rgAlbumPeak() const +{ + return 0; +} + +float +MP4::Tag::rgTrackGain() const +{ + return 0; +} + +float +MP4::Tag::rgTrackPeak() const +{ + return 0; +} + void MP4::Tag::setTitle(const String &value) { @@ -834,6 +858,26 @@ MP4::Tag::setTrack(unsigned int value) } } +void +MP4::Tag::setRGAlbumGain(float f) +{ +} + +void +MP4::Tag::setRGAlbumPeak(float f) +{ +} + +void +MP4::Tag::setRGTrackGain(float f) +{ +} + +void +MP4::Tag::setRGTrackPeak(float f) +{ +} + bool MP4::Tag::isEmpty() const { return d->items.isEmpty(); diff --git a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h index ccee8e06b..0f3923eaa 100644 --- a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h +++ b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h @@ -60,6 +60,10 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + float rgAlbumGain() const; + float rgAlbumPeak() const; + float rgTrackGain() const; + float rgTrackPeak() const; virtual void setTitle(const String &value); virtual void setArtist(const String &value); @@ -68,6 +72,10 @@ namespace TagLib { virtual void setGenre(const String &value); virtual void setYear(unsigned int value); virtual void setTrack(unsigned int value); + void setRGAlbumGain(float); + void setRGAlbumPeak(float); + void setRGTrackGain(float); + void setRGTrackPeak(float); virtual bool isEmpty() const; diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp index ca9304113..4dca6599c 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp @@ -162,6 +162,26 @@ unsigned int ID3v1::Tag::track() const return d->track; } +float ID3v1::Tag::rgAlbumGain() const +{ + return 0; +} + +float ID3v1::Tag::rgAlbumPeak() const +{ + return 0; +} + +float ID3v1::Tag::rgTrackGain() const +{ + return 0; +} + +float ID3v1::Tag::rgTrackPeak() const +{ + return 0; +} + void ID3v1::Tag::setTitle(const String &s) { d->title = s; @@ -197,6 +217,22 @@ void ID3v1::Tag::setTrack(unsigned int i) d->track = i < 256 ? i : 0; } +void ID3v1::Tag::setRGAlbumGain(float) +{ +} + +void ID3v1::Tag::setRGAlbumPeak(float) +{ +} + +void ID3v1::Tag::setRGTrackGain(float) +{ +} + +void ID3v1::Tag::setRGTrackPeak(float) +{ +} + unsigned int ID3v1::Tag::genreNumber() const { return d->genre; diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h index b61f06af9..d314c93ea 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h @@ -142,6 +142,10 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual float rgAlbumGain() const; + virtual float rgAlbumPeak() const; + virtual float rgTrackGain() const; + virtual float rgTrackPeak() const; virtual void setTitle(const String &s); virtual void setArtist(const String &s); @@ -150,6 +154,10 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setRGAlbumGain(float f); + virtual void setRGAlbumPeak(float f); + virtual void setRGTrackGain(float f); + virtual void setRGTrackPeak(float f); /*! * Returns the genre in number. diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp index 54dddf72f..8a2ede855 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp @@ -238,6 +238,40 @@ unsigned int ID3v2::Tag::track() const return 0; } +float ID3v2::Tag::rg(const String &type) const +{ + const FrameList &list = d->frameListMap["TXXX"]; + if (!list.isEmpty()) { + for (FrameList::ConstIterator it = list.begin(); it != list.end(); ++it) { + UserTextIdentificationFrame const* frame = static_cast(*it); + if (!frame->description().isNull() && frame->description() == type) { + return frame->toString().toFloat(); + } + } + } + return 0; +} + +float ID3v2::Tag::rgAlbumGain() const +{ + return rg("replaygain_album_gain"); +} + +float ID3v2::Tag::rgAlbumPeak() const +{ + return rg("replaygain_album_peak"); +} + +float ID3v2::Tag::rgTrackGain() const +{ + return rg("replaygain_track_gain"); +} + +float ID3v2::Tag::rgTrackPeak() const +{ + return rg("replaygain_track_peak"); +} + void ID3v2::Tag::setTitle(const String &s) { setTextFrame("TIT2", s); @@ -324,6 +358,52 @@ void ID3v2::Tag::setTrack(unsigned int i) setTextFrame("TRCK", String::number(i)); } +void ID3v2::Tag::setRG(const String &type, float f, bool peak) +{ + bool createdFrame = false; + UserTextIdentificationFrame * frame = NULL; + FrameList &list = d->frameListMap["TXXX"]; + for (FrameList::Iterator it = list.begin(); it != list.end(); ++it) { + if (static_cast(*it)->description() == type) { + frame = static_cast(*it); + break; + } + } + if (f == 0) { + if (frame) + removeFrame(frame); + return; + } + if (frame == NULL) { + frame = new UserTextIdentificationFrame; + frame->setDescription(type); + createdFrame = true; + } + frame->setText(String::number(f) + (peak ? "" : " dB")); + if (createdFrame) + addFrame(frame); +} + +void ID3v2::Tag::setRGAlbumGain(float f) +{ + setRG("replaygain_album_gain", f, false); +} + +void ID3v2::Tag::setRGAlbumPeak(float f) +{ + setRG("replaygain_album_peak", f, true); +} + +void ID3v2::Tag::setRGTrackGain(float f) +{ + setRG("replaygain_track_gain", f, false); +} + +void ID3v2::Tag::setRGTrackPeak(float f) +{ + setRG("replaygain_track_peak", f, true); +} + bool ID3v2::Tag::isEmpty() const { return d->frameList.isEmpty(); diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h index 74d1df1e7..86fae6341 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h @@ -164,6 +164,12 @@ namespace TagLib { virtual unsigned int year() const; virtual unsigned int track() const; + float rg(const String &type) const; + virtual float rgAlbumGain() const; + virtual float rgAlbumPeak() const; + virtual float rgTrackGain() const; + virtual float rgTrackPeak() const; + virtual void setTitle(const String &s); virtual void setArtist(const String &s); virtual void setAlbum(const String &s); @@ -172,6 +178,12 @@ namespace TagLib { virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + void setRG(const String &type, float f, bool peak); + virtual void setRGAlbumGain(float f); + virtual void setRGAlbumPeak(float f); + virtual void setRGTrackGain(float f); + virtual void setRGTrackPeak(float f); + virtual bool isEmpty() const; /*! diff --git a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp index f56bf810c..63d77fbeb 100644 --- a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp +++ b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp @@ -139,6 +139,34 @@ unsigned int Ogg::XiphComment::track() const return 0; } +float Ogg::XiphComment::rgAlbumGain() const +{ + if(d->fieldListMap["REPLAYGAIN_ALBUM_GAIN"].isEmpty()) + return 0; + return d->fieldListMap["REPLAYGAIN_ALBUM_GAIN"].front().toFloat(); +} + +float Ogg::XiphComment::rgAlbumPeak() const +{ + if(d->fieldListMap["REPLAYGAIN_ALBUM_PEAK"].isEmpty()) + return 0; + return d->fieldListMap["REPLAYGAIN_ALBUM_PEAK"].front().toFloat(); +} + +float Ogg::XiphComment::rgTrackGain() const +{ + if(d->fieldListMap["REPLAYGAIN_TRACK_GAIN"].isEmpty()) + return 0; + return d->fieldListMap["REPLAYGAIN_TRACK_GAIN"].front().toFloat(); +} + +float Ogg::XiphComment::rgTrackPeak() const +{ + if(d->fieldListMap["REPLAYGAIN_TRACK_PEAK"].isEmpty()) + return 0; + return d->fieldListMap["REPLAYGAIN_TRACK_PEAK"].front().toFloat(); +} + void Ogg::XiphComment::setTitle(const String &s) { addField("TITLE", s); @@ -189,6 +217,38 @@ void Ogg::XiphComment::setTrack(unsigned int i) addField("TRACKNUMBER", String::number(i)); } +void Ogg::XiphComment::setRGAlbumGain(float f) +{ + if (f == 0) + removeField("REPLAYGAIN_ALBUM_GAIN"); + else + addField("REPLAYGAIN_ALBUM_GAIN", String::number(f) + " dB"); +} + +void Ogg::XiphComment::setRGAlbumPeak(float f) +{ + if (f == 0) + removeField("REPLAYGAIN_ALBUM_PEAK"); + else + addField("REPLAYGAIN_ALBUM_PEAK", String::number(f)); +} + +void Ogg::XiphComment::setRGTrackGain(float f) +{ + if (f == 0) + removeField("REPLAYGAIN_TRACK_GAIN"); + else + addField("REPLAYGAIN_TRACK_GAIN", String::number(f) + " dB"); +} + +void Ogg::XiphComment::setRGTrackPeak(float f) +{ + if (f == 0) + removeField("REPLAYGAIN_TRACK_PEAK"); + else + addField("REPLAYGAIN_TRACK_PEAK", String::number(f)); +} + bool Ogg::XiphComment::isEmpty() const { for(FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) { diff --git a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h index 674d61697..74b927b38 100644 --- a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h +++ b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h @@ -87,6 +87,10 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual float rgAlbumGain() const; + virtual float rgAlbumPeak() const; + virtual float rgTrackGain() const; + virtual float rgTrackPeak() const; virtual void setTitle(const String &s); virtual void setArtist(const String &s); @@ -95,6 +99,10 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setRGAlbumGain(float f); + virtual void setRGAlbumPeak(float f); + virtual void setRGTrackGain(float f); + virtual void setRGTrackPeak(float f); virtual bool isEmpty() const; diff --git a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp index df1cfbeef..a84e96569 100644 --- a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp +++ b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp @@ -123,6 +123,26 @@ unsigned int RIFF::Info::Tag::track() const return fieldText("IPRT").toInt(); } +float RIFF::Info::Tag::rgAlbumGain() const +{ + return 0; +} + +float RIFF::Info::Tag::rgAlbumPeak() const +{ + return 0; +} + +float RIFF::Info::Tag::rgTrackGain() const +{ + return 0; +} + +float RIFF::Info::Tag::rgTrackPeak() const +{ + return 0; +} + void RIFF::Info::Tag::setTitle(const String &s) { setFieldText("INAM", s); @@ -164,6 +184,22 @@ void RIFF::Info::Tag::setTrack(unsigned int i) d->fieldListMap.erase("IPRT"); } +void RIFF::Info::Tag::setRGAlbumGain(float) +{ +} + +void RIFF::Info::Tag::setRGAlbumPeak(float) +{ +} + +void RIFF::Info::Tag::setRGTrackGain(float) +{ +} + +void RIFF::Info::Tag::setRGTrackPeak(float) +{ +} + bool RIFF::Info::Tag::isEmpty() const { return d->fieldListMap.isEmpty(); diff --git a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h index d1f0297db..dadc91a6e 100644 --- a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h +++ b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h @@ -109,6 +109,10 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual float rgAlbumGain() const; + virtual float rgAlbumPeak() const; + virtual float rgTrackGain() const; + virtual float rgTrackPeak() const; virtual void setTitle(const String &s); virtual void setArtist(const String &s); @@ -117,6 +121,10 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setRGAlbumGain(float f); + virtual void setRGAlbumPeak(float f); + virtual void setRGTrackGain(float f); + virtual void setRGTrackPeak(float f); virtual bool isEmpty() const; diff --git a/Frameworks/TagLib/taglib/taglib/tag.h b/Frameworks/TagLib/taglib/taglib/tag.h index be9628c81..b7de76d7f 100644 --- a/Frameworks/TagLib/taglib/taglib/tag.h +++ b/Frameworks/TagLib/taglib/taglib/tag.h @@ -119,6 +119,30 @@ namespace TagLib { */ virtual unsigned int track() const = 0; + /*! + * Returns the ReplayGain album gain; if there is no gain level set, this + * will return 0. + */ + virtual float rgAlbumGain() const = 0; + + /*! + * Returns the ReplayGain album peak; if there is no gain level set, this + * will return 0. + */ + virtual float rgAlbumPeak() const = 0; + + /*! + * Returns the ReplayGain track gain; if there is no gain level set, this + * will return 0. + */ + virtual float rgTrackGain() const = 0; + + /*! + * Returns the ReplayGain track peak; if there is no gain level set, this + * will return 0. + */ + virtual float rgTrackPeak() const = 0; + /*! * Sets the title to \a s. If \a s is String::null then this value will be * cleared. @@ -162,6 +186,30 @@ namespace TagLib { */ virtual void setTrack(unsigned int i) = 0; + /*! + * Sets the ReplayGain album gain to \a f. If \a f is 0 then this value will + * be cleared. + */ + virtual void setRGAlbumGain(float i) = 0; + + /*! + * Sets the ReplayGain album peak to \a f. If \a f is 0 then this value will + * be cleared. + */ + virtual void setRGAlbumPeak(float i) = 0; + + /*! + * Sets the ReplayGain track gain to \a f. If \a f is 0 then this value will + * be cleared. + */ + virtual void setRGTrackGain(float i) = 0; + + /*! + * Sets the ReplayGain track peak to \a f. If \a f is 0 then this value will + * be cleared. + */ + virtual void setRGTrackPeak(float i) = 0; + /*! * Returns true if the tag does not contain any data. This should be * reimplemented in subclasses that provide more than the basic tagging diff --git a/Frameworks/TagLib/taglib/taglib/tagunion.cpp b/Frameworks/TagLib/taglib/taglib/tagunion.cpp index 64d786b9a..46bb7cd65 100644 --- a/Frameworks/TagLib/taglib/taglib/tagunion.cpp +++ b/Frameworks/TagLib/taglib/taglib/tagunion.cpp @@ -53,6 +53,15 @@ using namespace TagLib; return tag(2)->method(); \ return 0 +#define floatUnion(method) \ + if(tag(0) && tag(0)->method() != 0) \ + return tag(0)->method(); \ + if(tag(1) && tag(1)->method() != 0) \ + return tag(1)->method(); \ + if(tag(2) && tag(2)->method() != 0) \ + return tag(2)->method(); \ + return 0 + #define setUnion(method, value) \ if(tag(0)) \ tag(0)->set##method(value); \ @@ -199,6 +208,26 @@ unsigned int TagUnion::track() const numberUnion(track); } +float TagUnion::rgAlbumGain() const +{ + floatUnion(rgAlbumGain); +} + +float TagUnion::rgAlbumPeak() const +{ + floatUnion(rgAlbumPeak); +} + +float TagUnion::rgTrackGain() const +{ + floatUnion(rgTrackGain); +} + +float TagUnion::rgTrackPeak() const +{ + floatUnion(rgTrackPeak); +} + void TagUnion::setTitle(const String &s) { setUnion(Title, s); @@ -234,6 +263,26 @@ void TagUnion::setTrack(unsigned int i) setUnion(Track, i); } +void TagUnion::setRGAlbumGain(float f) +{ + setUnion(RGAlbumGain, f); +} + +void TagUnion::setRGAlbumPeak(float f) +{ + setUnion(RGAlbumPeak, f); +} + +void TagUnion::setRGTrackGain(float f) +{ + setUnion(RGTrackGain, f); +} + +void TagUnion::setRGTrackPeak(float f) +{ + setUnion(RGTrackPeak, f); +} + bool TagUnion::isEmpty() const { if(d->tags[0] && !d->tags[0]->isEmpty()) diff --git a/Frameworks/TagLib/taglib/taglib/tagunion.h b/Frameworks/TagLib/taglib/taglib/tagunion.h index 1eb38a01d..92efc8383 100644 --- a/Frameworks/TagLib/taglib/taglib/tagunion.h +++ b/Frameworks/TagLib/taglib/taglib/tagunion.h @@ -66,6 +66,10 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual float rgAlbumGain() const; + virtual float rgAlbumPeak() const; + virtual float rgTrackGain() const; + virtual float rgTrackPeak() const; virtual void setTitle(const String &s); virtual void setArtist(const String &s); @@ -74,6 +78,10 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setRGAlbumGain(float f); + virtual void setRGAlbumPeak(float f); + virtual void setRGTrackGain(float f); + virtual void setRGTrackPeak(float f); virtual bool isEmpty() const; template T *access(int index, bool create) diff --git a/Frameworks/TagLib/taglib/taglib/toolkit/tstring.cpp b/Frameworks/TagLib/taglib/taglib/toolkit/tstring.cpp index c60a3e2ed..bf28feb18 100644 --- a/Frameworks/TagLib/taglib/taglib/toolkit/tstring.cpp +++ b/Frameworks/TagLib/taglib/taglib/toolkit/tstring.cpp @@ -24,6 +24,7 @@ ***************************************************************************/ #include +#include #include #include @@ -514,6 +515,27 @@ int String::toInt(bool *ok) const return static_cast(value); } +float String::toFloat() const +{ + return toFloat(0); +} + +float String::toFloat(bool *ok) const +{ + const wchar_t *begin = d->data.c_str(); + wchar_t *end; + errno = 0; + const float value = ::wcstof(begin, &end); + + // Has wcstof() consumed the entire string and not overflowed? + if(ok) { + *ok = (errno == 0 && end > begin && *end == L'\0'); + *ok = (*ok && value > FLT_MIN && value < FLT_MAX); + } + + return value; +} + String String::stripWhiteSpace() const { static const wchar_t *WhiteSpaceChars = L"\t\n\f\r "; @@ -549,6 +571,11 @@ String String::number(int n) // static return Utils::formatString("%d", n); } +String String::numberFloat(float n) // static +{ + return Utils::formatString("%f", n); +} + wchar_t &String::operator[](int i) { detach(); diff --git a/Frameworks/TagLib/taglib/taglib/toolkit/tstring.h b/Frameworks/TagLib/taglib/taglib/toolkit/tstring.h index 7028aab2f..27c81eabc 100644 --- a/Frameworks/TagLib/taglib/taglib/toolkit/tstring.h +++ b/Frameworks/TagLib/taglib/taglib/toolkit/tstring.h @@ -372,6 +372,24 @@ namespace TagLib { */ int toInt(bool *ok) const; + /*! + * Convert the string to a float. + * + * Returns the float if the conversion was successful or 0 if the + * string does not represent a number. + */ + // BIC: merge with the method below + float toFloat() const; + + /*! + * Convert the string to a float. + * + * If the conversion was successful, it sets the value of \a *ok to + * true and returns the float. Otherwise it sets \a *ok to false + * and the result is undefined. + */ + float toFloat(bool *ok) const; + /*! * Returns a string with the leading and trailing whitespace stripped. */ @@ -392,6 +410,11 @@ namespace TagLib { */ static String number(int n); + /*! + * Converts the base-10 float \a n to a string. + */ + static String numberFloat(float n); + /*! * Returns a reference to the character at position \a i. */ diff --git a/Plugins/TagLib/TagLibMetadataReader.m b/Plugins/TagLib/TagLibMetadataReader.m index 401323d78..b17d043fa 100644 --- a/Plugins/TagLib/TagLibMetadataReader.m +++ b/Plugins/TagLib/TagLibMetadataReader.m @@ -72,6 +72,7 @@ { TagLib::String artist, title, album, genre, comment; int year, track; + float rgAlbumGain, rgAlbumPeak, rgTrackGain, rgTrackPeak; artist = tag->artist(); title = tag->title();; @@ -84,6 +85,15 @@ track = tag->track(); [dict setObject:[NSNumber numberWithInt:track] forKey:@"track"]; + + rgAlbumGain = tag->rgAlbumGain(); + rgAlbumPeak = tag->rgAlbumPeak(); + rgTrackGain = tag->rgTrackGain(); + rgTrackPeak = tag->rgTrackPeak(); + [dict setObject:[NSNumber numberWithFloat:rgAlbumGain] forKey:@"replayGainAlbumGain"]; + [dict setObject:[NSNumber numberWithFloat:rgAlbumPeak] forKey:@"replayGainAlbumPeak"]; + [dict setObject:[NSNumber numberWithFloat:rgTrackGain] forKey:@"replayGainTrackGain"]; + [dict setObject:[NSNumber numberWithFloat:rgTrackPeak] forKey:@"replayGainTrackPeak"]; if (!artist.isEmpty()) [dict setObject:[NSString stringWithUTF8String:artist.toCString(true)] forKey:@"artist"]; @@ -98,18 +108,6 @@ [dict setObject:[NSString stringWithUTF8String:genre.toCString(true)] forKey:@"genre"]; } - if (auto props = dynamic_cast(f.audioProperties())) { - float rgAlbumGain, rgAlbumPeak, rgTrackGain, rgTrackPeak; - rgAlbumGain = 64.82f - (props->albumGain() / 256.0f); - rgAlbumPeak = props->albumPeak() / 256.0f; - rgTrackGain = 64.82f - (props->trackGain() / 256.0f); - rgTrackPeak = props->trackPeak() / 256.0f; - [dict setObject:[NSNumber numberWithFloat:rgAlbumGain] forKey:@"replayGainAlbumGain"]; - [dict setObject:[NSNumber numberWithFloat:rgAlbumPeak] forKey:@"replayGainAlbumPeak"]; - [dict setObject:[NSNumber numberWithFloat:rgTrackGain] forKey:@"replayGainTrackGain"]; - [dict setObject:[NSNumber numberWithFloat:rgTrackPeak] forKey:@"replayGainTrackPeak"]; - } - // Try to load the image. NSData * image = nil;