From a21242db5541fc983de10a4ee5387b42b48c4eb0 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Thu, 23 Feb 2023 17:41:12 -0800 Subject: [PATCH] TagLib: Implement unsynced lyrics tag support Implement unsynced lyrics tag reading and writing into TagLib. Signed-off-by: Christopher Snowhill --- .../TagLib/taglib/taglib/ape/apetag.cpp | 16 ++++++++++ Frameworks/TagLib/taglib/taglib/ape/apetag.h | 2 ++ .../TagLib/taglib/taglib/asf/asftag.cpp | 12 +++++++ Frameworks/TagLib/taglib/taglib/asf/asftag.h | 12 +++++++ .../TagLib/taglib/taglib/mod/modtag.cpp | 9 ++++++ Frameworks/TagLib/taglib/taglib/mod/modtag.h | 10 ++++++ .../taglib/taglib/mpeg/id3v1/id3v1tag.cpp | 9 ++++++ .../taglib/taglib/mpeg/id3v1/id3v1tag.h | 2 ++ .../taglib/taglib/mpeg/id3v2/id3v2tag.cpp | 32 +++++++++++++++++++ .../taglib/taglib/mpeg/id3v2/id3v2tag.h | 2 ++ .../TagLib/taglib/taglib/riff/wav/infotag.cpp | 9 ++++++ .../TagLib/taglib/taglib/riff/wav/infotag.h | 2 ++ Frameworks/TagLib/taglib/taglib/tag.cpp | 18 +++++++++++ Frameworks/TagLib/taglib/taglib/tag.h | 12 +++++++ Frameworks/TagLib/taglib/taglib/tagunion.cpp | 10 ++++++ Frameworks/TagLib/taglib/taglib/tagunion.h | 2 ++ .../taglib/taglib/toolkit/tpropertymap.h | 1 + 17 files changed, 160 insertions(+) diff --git a/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp b/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp index 0d4d575eb..f1d1c2eb5 100644 --- a/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp +++ b/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp @@ -146,6 +146,17 @@ String APE::Tag::album() const return d->itemListMap["ALBUM"].values().toString(); } +String APE::Tag::unsyncedlyrics() const +{ + if(!d->itemListMap["UNSYNCEDLYRICS"].isEmpty()) + return d->itemListMap["UNSYNCEDLYRICS"].values().toString(); + if(!d->itemListMap["UNSYNCED LYRICS"].isEmpty()) + return d->itemListMap["UNSYNCED LYRICS"].values().toString(); + if(!d->itemListMap["LYRICS"].isEmpty()) + return d->itemListMap["LYRICS"].values().toString(); + return String(); +} + String APE::Tag::comment() const { if(d->itemListMap["COMMENT"].isEmpty()) @@ -241,6 +252,11 @@ void APE::Tag::setAlbum(const String &s) addValue("ALBUM", s, true); } +void APE::Tag::setUnsyncedlyrics(const String &s) +{ + addValue("UNSYNCED LYRICS", s); +} + void APE::Tag::setComment(const String &s) { addValue("COMMENT", s, true); diff --git a/Frameworks/TagLib/taglib/taglib/ape/apetag.h b/Frameworks/TagLib/taglib/taglib/ape/apetag.h index 293cff1da..6459e6488 100644 --- a/Frameworks/TagLib/taglib/taglib/ape/apetag.h +++ b/Frameworks/TagLib/taglib/taglib/ape/apetag.h @@ -91,6 +91,7 @@ namespace TagLib { virtual String albumartist() const; virtual String artist() const; virtual String album() const; + virtual String unsyncedlyrics() const; virtual String comment() const; virtual String genre() const; virtual unsigned int year() const; @@ -107,6 +108,7 @@ namespace TagLib { virtual void setAlbumArtist(const String &s); virtual void setArtist(const String &s); virtual void setAlbum(const String &s); + virtual void setUnsyncedlyrics(const String &s); virtual void setComment(const String &s); virtual void setGenre(const String &s); virtual void setYear(unsigned int i); diff --git a/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp b/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp index fd3d7e673..6758915e2 100644 --- a/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp +++ b/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp @@ -72,6 +72,13 @@ String ASF::Tag::album() const return String(); } +String ASF::Tag::unsyncedlyrics() const +{ + if(d->attributeListMap.contains("WM/Lyrics")) + return d->attributeListMap["WM/Lyrics"][0].toString(); + return String(); +} + String ASF::Tag::copyright() const { return d->copyright; @@ -193,6 +200,11 @@ void ASF::Tag::setAlbum(const String &value) setAttribute("WM/AlbumTitle", value); } +void ASF::Tag::setUnsyncedlyrics(const String &value) +{ + setAttribute("WM/Lyrics", value); +} + void ASF::Tag::setGenre(const String &value) { setAttribute("WM/Genre", value); diff --git a/Frameworks/TagLib/taglib/taglib/asf/asftag.h b/Frameworks/TagLib/taglib/taglib/asf/asftag.h index 6fd3715b2..2791beb80 100644 --- a/Frameworks/TagLib/taglib/taglib/asf/asftag.h +++ b/Frameworks/TagLib/taglib/taglib/asf/asftag.h @@ -70,6 +70,12 @@ namespace TagLib { */ virtual String album() const; + /*! + * Returns the unsynchronized lyrics; if no unsynced lyrics are + * present in the tag String::null will be returned. + */ + virtual String unsyncedlyrics() const; + /*! * Returns the track comment. */ @@ -132,6 +138,12 @@ namespace TagLib { * cleared. */ virtual void setAlbum(const String &s); + + /*! + * Sets the unsynced lyrics to \a s. if \a s is String::null then this + * value will be cleared. + */ + virtual void setUnsyncedlyrics(const String &s); /*! * Sets the comment to \a s. diff --git a/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp b/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp index be8ae3cda..0bbd02c98 100644 --- a/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp @@ -74,6 +74,11 @@ String Mod::Tag::album() const return String(); } +String Mod::Tag::unsyncedlyrics() const +{ + return String(); +} + String Mod::Tag::comment() const { return d->comment; @@ -151,6 +156,10 @@ void Mod::Tag::setAlbum(const String &) { } +void Mod::Tag::setUnsyncedlyrics(const String &) +{ +} + void Mod::Tag::setComment(const String &comment) { d->comment = comment; diff --git a/Frameworks/TagLib/taglib/taglib/mod/modtag.h b/Frameworks/TagLib/taglib/taglib/mod/modtag.h index f6842902c..ba9d11e75 100644 --- a/Frameworks/TagLib/taglib/taglib/mod/modtag.h +++ b/Frameworks/TagLib/taglib/taglib/mod/modtag.h @@ -72,6 +72,11 @@ namespace TagLib { */ virtual String album() const; + /*! + * Not supported by module files. Therefore always returns String::null. + */ + virtual String unsyncedlyrics() const; + /*! * Returns the track comment derived from the instrument/sample/pattern * names; if no comment is present in the tag String::null will be @@ -163,6 +168,11 @@ namespace TagLib { */ virtual void setAlbum(const String &album); + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setUnsyncedlyrics(const String &unsyncedlyrics); + /*! * Sets the comment to \a comment. If \a comment is String::null then * this value will be cleared. diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp index 693b3875a..3b12e87c1 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp @@ -147,6 +147,11 @@ String ID3v1::Tag::album() const return d->album; } +String ID3v1::Tag::unsyncedlyrics() const +{ + return String(); +} + String ID3v1::Tag::comment() const { return d->comment; @@ -221,6 +226,10 @@ void ID3v1::Tag::setAlbum(const String &s) d->album = s; } +void ID3v1::Tag::setUnsyncedlyrics(const String &s) +{ +} + void ID3v1::Tag::setComment(const String &s) { d->comment = s; diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h index 831047f8c..24ed105ef 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h @@ -140,6 +140,7 @@ namespace TagLib { virtual String artist() const; virtual String album() const; virtual String comment() const; + virtual String unsyncedlyrics() const; virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; @@ -156,6 +157,7 @@ namespace TagLib { virtual void setArtist(const String &s); virtual void setAlbum(const String &s); virtual void setComment(const String &s); + virtual void setUnsyncedlyrics(const String &s); virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp index 7bd21523e..4d0269eb3 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp @@ -170,6 +170,13 @@ String ID3v2::Tag::album() const return String(); } +String ID3v2::Tag::unsyncedlyrics() const +{ + if(!d->frameListMap["USLT"].isEmpty()) + return d->frameListMap["USLT"].front()->toString(); + return String(); +} + String ID3v2::Tag::comment() const { const FrameList &comments = d->frameListMap["COMM"]; @@ -350,6 +357,31 @@ void ID3v2::Tag::setAlbum(const String &s) setTextFrame("TALB", s); } +void ID3v2::Tag::setUnsyncedlyrics(const String &s) +{ + if(s.isEmpty()) { + removeFrames("USLT"); + return; + } + + const FrameList &unsyncedlyrics = d->frameListMap["USLT"]; + + if(!unsyncedlyrics.isEmpty()) { + for(FrameList::ConstIterator it = unsyncedlyrics.begin(); it != unsyncedlyrics.end(); ++it) { + UnsynchronizedLyricsFrame *frame = dynamic_cast(*it); + if(frame && (frame->description().isEmpty() || frame->description() == "LYRICS")) { + (*it)->setText(s); + return; + } + } + } + + UnsynchronizedLyricsFrame *f = new UnsynchronizedLyricsFrame(d->factory->defaultTextEncoding()); + addFrame(f); + f->setDescription("LYRICS"); + f->setText(s); +} + void ID3v2::Tag::setComment(const String &s) { if(s.isEmpty()) { diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h index a176dbdda..156427069 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h @@ -161,6 +161,7 @@ namespace TagLib { virtual String artist() const; virtual String album() const; virtual String comment() const; + virtual String unsyncedlyrics() const; virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; @@ -180,6 +181,7 @@ namespace TagLib { virtual void setArtist(const String &s); virtual void setAlbum(const String &s); virtual void setComment(const String &s); + virtual void setUnsyncedlyrics(const String &s); virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); diff --git a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp index 0eac54c39..17519e6df 100644 --- a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp +++ b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp @@ -108,6 +108,11 @@ String RIFF::Info::Tag::album() const return fieldText("IPRD"); } +String RIFF::Info::Tag::unsyncedlyrics() const +{ + return String(); +} + String RIFF::Info::Tag::comment() const { return fieldText("ICMT"); @@ -182,6 +187,10 @@ void RIFF::Info::Tag::setAlbum(const String &s) setFieldText("IPRD", s); } +void RIFF::Info::Tag::setUnsyncedlyrics(const String &) +{ +} + void RIFF::Info::Tag::setComment(const String &s) { setFieldText("ICMT", s); diff --git a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h index 857dcfc8e..4eaa31e3c 100644 --- a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h +++ b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h @@ -106,6 +106,7 @@ namespace TagLib { virtual String albumartist() const; virtual String artist() const; virtual String album() const; + virtual String unsyncedlyrics() const; virtual String comment() const; virtual String genre() const; virtual unsigned int year() const; @@ -122,6 +123,7 @@ namespace TagLib { virtual void setAlbumArtist(const String &s); virtual void setArtist(const String &s); virtual void setAlbum(const String &s); + virtual void setUnsyncedlyrics(const String &s); virtual void setComment(const String &s); virtual void setGenre(const String &s); virtual void setYear(unsigned int i); diff --git a/Frameworks/TagLib/taglib/taglib/tag.cpp b/Frameworks/TagLib/taglib/taglib/tag.cpp index 5164de08b..79c40abe4 100644 --- a/Frameworks/TagLib/taglib/taglib/tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/tag.cpp @@ -50,6 +50,7 @@ bool Tag::isEmpty() const albumartist().isEmpty() && artist().isEmpty() && album().isEmpty() && + unsyncedlyrics().isEmpty() && comment().isEmpty() && genre().isEmpty() && year() == 0 && @@ -68,6 +69,8 @@ PropertyMap Tag::properties() const map["ARTIST"].append(artist()); if(!(album().isEmpty())) map["ALBUM"].append(album()); + if(!(unsyncedlyrics().isEmpty())) + map["UNSYNCEDLYRICS"].append(unsyncedlyrics()); if(!(comment().isEmpty())) map["COMMENT"].append(comment()); if(!(genre().isEmpty())) @@ -119,6 +122,18 @@ PropertyMap Tag::setProperties(const PropertyMap &origProps) } else setAlbum(String()); + if(properties.contains("UNSYNCEDLYRICS") || + properties.contains("UNSYNCED LYRICS") || + properties.contains("LYRICS")) { + if(properties.contains("UNSYNCEDLYRICS")) + setUnsyncedlyrics(properties["UNSYNCEDLYRICS"].front()); + else if(properties.contains("UNSYNCED LYRICS")) + setUnsyncedlyrics(properties["UNSYNCED LYRICS"].front()); + else + setUnsyncedlyrics(properties["LYRICS"].front()); + oneValueSet.append("UNSYNCEDLYRICS"); + } + if(properties.contains("COMMENT")) { setComment(properties["COMMENT"].front()); oneValueSet.append("COMMENT"); @@ -185,6 +200,7 @@ void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static target->setAlbumArtist(source->albumartist()); target->setArtist(source->artist()); target->setAlbum(source->album()); + target->setUnsyncedlyrics(source->unsyncedlyrics()); target->setComment(source->comment()); target->setGenre(source->genre()); target->setYear(source->year()); @@ -200,6 +216,8 @@ void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static target->setArtist(source->artist()); if(target->album().isEmpty()) target->setAlbum(source->album()); + if(target->unsyncedlyrics().isEmpty()) + target->setUnsyncedlyrics(source->unsyncedlyrics()); if(target->comment().isEmpty()) target->setComment(source->comment()); if(target->genre().isEmpty()) diff --git a/Frameworks/TagLib/taglib/taglib/tag.h b/Frameworks/TagLib/taglib/taglib/tag.h index 1fd763016..5b2d36230 100644 --- a/Frameworks/TagLib/taglib/taglib/tag.h +++ b/Frameworks/TagLib/taglib/taglib/tag.h @@ -102,6 +102,12 @@ namespace TagLib { */ virtual String album() const = 0; + /*! + * Returns the unsynced lyrics; if no unsynced lyrics are present + * in the tag String::null will be returned. + */ + virtual String unsyncedlyrics() const = 0; + /*! * Returns the track comment; if no comment is present in the tag * String::null will be returned. @@ -191,6 +197,12 @@ namespace TagLib { */ virtual void setAlbum(const String &s) = 0; + /*! + * Sets the unsynced lyrics to \a s. If \a s is String::null then this + * value will be cleared. + */ + virtual void setUnsyncedlyrics(const String &s) = 0; + /*! * Sets the comment to \a s. If \a s is String::null then this value will be * cleared. diff --git a/Frameworks/TagLib/taglib/taglib/tagunion.cpp b/Frameworks/TagLib/taglib/taglib/tagunion.cpp index 47cb6bebf..856247632 100644 --- a/Frameworks/TagLib/taglib/taglib/tagunion.cpp +++ b/Frameworks/TagLib/taglib/taglib/tagunion.cpp @@ -186,6 +186,11 @@ String TagUnion::album() const stringUnion(album); } +String TagUnion::unsyncedlyrics() const +{ + stringUnion(unsyncedlyrics); +} + String TagUnion::comment() const { stringUnion(comment); @@ -261,6 +266,11 @@ void TagUnion::setAlbum(const String &s) setUnion(Album, s); } +void TagUnion::setUnsyncedlyrics(const String &s) +{ + setUnion(Unsyncedlyrics, s); +} + void TagUnion::setComment(const String &s) { setUnion(Comment, s); diff --git a/Frameworks/TagLib/taglib/taglib/tagunion.h b/Frameworks/TagLib/taglib/taglib/tagunion.h index 3da454692..f8d93c898 100644 --- a/Frameworks/TagLib/taglib/taglib/tagunion.h +++ b/Frameworks/TagLib/taglib/taglib/tagunion.h @@ -63,6 +63,7 @@ namespace TagLib { virtual String albumartist() const; virtual String artist() const; virtual String album() const; + virtual String unsyncedlyrics() const; virtual String comment() const; virtual String genre() const; virtual unsigned int year() const; @@ -79,6 +80,7 @@ namespace TagLib { virtual void setAlbumArtist(const String &s); virtual void setArtist(const String &s); virtual void setAlbum(const String &s); + virtual void setUnsyncedlyrics(const String &s); virtual void setComment(const String &s); virtual void setGenre(const String &s); virtual void setYear(unsigned int i); diff --git a/Frameworks/TagLib/taglib/taglib/toolkit/tpropertymap.h b/Frameworks/TagLib/taglib/taglib/toolkit/tpropertymap.h index ab6d512b5..78eec3041 100644 --- a/Frameworks/TagLib/taglib/taglib/toolkit/tpropertymap.h +++ b/Frameworks/TagLib/taglib/taglib/toolkit/tpropertymap.h @@ -61,6 +61,7 @@ namespace TagLib { * - ORIGINALDATE * - GENRE * - COMMENT + * - UNSYNCEDLYRICS * * Sort names: *