TagLib: Implement unsynced lyrics tag support

Implement unsynced lyrics tag reading and writing into TagLib.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
main
Christopher Snowhill 2023-02-23 17:41:12 -08:00
parent 7e2a286b83
commit a21242db55
No known key found for this signature in database
17 changed files with 160 additions and 0 deletions

View File

@ -146,6 +146,17 @@ String APE::Tag::album() const
return d->itemListMap["ALBUM"].values().toString(); 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 String APE::Tag::comment() const
{ {
if(d->itemListMap["COMMENT"].isEmpty()) if(d->itemListMap["COMMENT"].isEmpty())
@ -241,6 +252,11 @@ void APE::Tag::setAlbum(const String &s)
addValue("ALBUM", s, true); addValue("ALBUM", s, true);
} }
void APE::Tag::setUnsyncedlyrics(const String &s)
{
addValue("UNSYNCED LYRICS", s);
}
void APE::Tag::setComment(const String &s) void APE::Tag::setComment(const String &s)
{ {
addValue("COMMENT", s, true); addValue("COMMENT", s, true);

View File

@ -91,6 +91,7 @@ namespace TagLib {
virtual String albumartist() const; virtual String albumartist() const;
virtual String artist() const; virtual String artist() const;
virtual String album() const; virtual String album() const;
virtual String unsyncedlyrics() const;
virtual String comment() const; virtual String comment() const;
virtual String genre() const; virtual String genre() const;
virtual unsigned int year() const; virtual unsigned int year() const;
@ -107,6 +108,7 @@ namespace TagLib {
virtual void setAlbumArtist(const String &s); virtual void setAlbumArtist(const String &s);
virtual void setArtist(const String &s); virtual void setArtist(const String &s);
virtual void setAlbum(const String &s); virtual void setAlbum(const String &s);
virtual void setUnsyncedlyrics(const String &s);
virtual void setComment(const String &s); virtual void setComment(const String &s);
virtual void setGenre(const String &s); virtual void setGenre(const String &s);
virtual void setYear(unsigned int i); virtual void setYear(unsigned int i);

View File

@ -72,6 +72,13 @@ String ASF::Tag::album() const
return String(); 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 String ASF::Tag::copyright() const
{ {
return d->copyright; return d->copyright;
@ -193,6 +200,11 @@ void ASF::Tag::setAlbum(const String &value)
setAttribute("WM/AlbumTitle", value); setAttribute("WM/AlbumTitle", value);
} }
void ASF::Tag::setUnsyncedlyrics(const String &value)
{
setAttribute("WM/Lyrics", value);
}
void ASF::Tag::setGenre(const String &value) void ASF::Tag::setGenre(const String &value)
{ {
setAttribute("WM/Genre", value); setAttribute("WM/Genre", value);

View File

@ -70,6 +70,12 @@ namespace TagLib {
*/ */
virtual String album() const; 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. * Returns the track comment.
*/ */
@ -133,6 +139,12 @@ namespace TagLib {
*/ */
virtual void setAlbum(const String &s); 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. * Sets the comment to \a s.
*/ */

View File

@ -74,6 +74,11 @@ String Mod::Tag::album() const
return String(); return String();
} }
String Mod::Tag::unsyncedlyrics() const
{
return String();
}
String Mod::Tag::comment() const String Mod::Tag::comment() const
{ {
return d->comment; 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) void Mod::Tag::setComment(const String &comment)
{ {
d->comment = comment; d->comment = comment;

View File

@ -72,6 +72,11 @@ namespace TagLib {
*/ */
virtual String album() const; 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 * Returns the track comment derived from the instrument/sample/pattern
* names; if no comment is present in the tag String::null will be * 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); 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 * Sets the comment to \a comment. If \a comment is String::null then
* this value will be cleared. * this value will be cleared.

View File

@ -147,6 +147,11 @@ String ID3v1::Tag::album() const
return d->album; return d->album;
} }
String ID3v1::Tag::unsyncedlyrics() const
{
return String();
}
String ID3v1::Tag::comment() const String ID3v1::Tag::comment() const
{ {
return d->comment; return d->comment;
@ -221,6 +226,10 @@ void ID3v1::Tag::setAlbum(const String &s)
d->album = s; d->album = s;
} }
void ID3v1::Tag::setUnsyncedlyrics(const String &s)
{
}
void ID3v1::Tag::setComment(const String &s) void ID3v1::Tag::setComment(const String &s)
{ {
d->comment = s; d->comment = s;

View File

@ -140,6 +140,7 @@ namespace TagLib {
virtual String artist() const; virtual String artist() const;
virtual String album() const; virtual String album() const;
virtual String comment() const; virtual String comment() const;
virtual String unsyncedlyrics() const;
virtual String genre() const; virtual String genre() const;
virtual unsigned int year() const; virtual unsigned int year() const;
virtual unsigned int track() const; virtual unsigned int track() const;
@ -156,6 +157,7 @@ namespace TagLib {
virtual void setArtist(const String &s); virtual void setArtist(const String &s);
virtual void setAlbum(const String &s); virtual void setAlbum(const String &s);
virtual void setComment(const String &s); virtual void setComment(const String &s);
virtual void setUnsyncedlyrics(const String &s);
virtual void setGenre(const String &s); virtual void setGenre(const String &s);
virtual void setYear(unsigned int i); virtual void setYear(unsigned int i);
virtual void setTrack(unsigned int i); virtual void setTrack(unsigned int i);

View File

@ -170,6 +170,13 @@ String ID3v2::Tag::album() const
return String(); 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 String ID3v2::Tag::comment() const
{ {
const FrameList &comments = d->frameListMap["COMM"]; const FrameList &comments = d->frameListMap["COMM"];
@ -350,6 +357,31 @@ void ID3v2::Tag::setAlbum(const String &s)
setTextFrame("TALB", 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<UnsynchronizedLyricsFrame *>(*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) void ID3v2::Tag::setComment(const String &s)
{ {
if(s.isEmpty()) { if(s.isEmpty()) {

View File

@ -161,6 +161,7 @@ namespace TagLib {
virtual String artist() const; virtual String artist() const;
virtual String album() const; virtual String album() const;
virtual String comment() const; virtual String comment() const;
virtual String unsyncedlyrics() const;
virtual String genre() const; virtual String genre() const;
virtual unsigned int year() const; virtual unsigned int year() const;
virtual unsigned int track() const; virtual unsigned int track() const;
@ -180,6 +181,7 @@ namespace TagLib {
virtual void setArtist(const String &s); virtual void setArtist(const String &s);
virtual void setAlbum(const String &s); virtual void setAlbum(const String &s);
virtual void setComment(const String &s); virtual void setComment(const String &s);
virtual void setUnsyncedlyrics(const String &s);
virtual void setGenre(const String &s); virtual void setGenre(const String &s);
virtual void setYear(unsigned int i); virtual void setYear(unsigned int i);
virtual void setTrack(unsigned int i); virtual void setTrack(unsigned int i);

View File

@ -108,6 +108,11 @@ String RIFF::Info::Tag::album() const
return fieldText("IPRD"); return fieldText("IPRD");
} }
String RIFF::Info::Tag::unsyncedlyrics() const
{
return String();
}
String RIFF::Info::Tag::comment() const String RIFF::Info::Tag::comment() const
{ {
return fieldText("ICMT"); return fieldText("ICMT");
@ -182,6 +187,10 @@ void RIFF::Info::Tag::setAlbum(const String &s)
setFieldText("IPRD", s); setFieldText("IPRD", s);
} }
void RIFF::Info::Tag::setUnsyncedlyrics(const String &)
{
}
void RIFF::Info::Tag::setComment(const String &s) void RIFF::Info::Tag::setComment(const String &s)
{ {
setFieldText("ICMT", s); setFieldText("ICMT", s);

View File

@ -106,6 +106,7 @@ namespace TagLib {
virtual String albumartist() const; virtual String albumartist() const;
virtual String artist() const; virtual String artist() const;
virtual String album() const; virtual String album() const;
virtual String unsyncedlyrics() const;
virtual String comment() const; virtual String comment() const;
virtual String genre() const; virtual String genre() const;
virtual unsigned int year() const; virtual unsigned int year() const;
@ -122,6 +123,7 @@ namespace TagLib {
virtual void setAlbumArtist(const String &s); virtual void setAlbumArtist(const String &s);
virtual void setArtist(const String &s); virtual void setArtist(const String &s);
virtual void setAlbum(const String &s); virtual void setAlbum(const String &s);
virtual void setUnsyncedlyrics(const String &s);
virtual void setComment(const String &s); virtual void setComment(const String &s);
virtual void setGenre(const String &s); virtual void setGenre(const String &s);
virtual void setYear(unsigned int i); virtual void setYear(unsigned int i);

View File

@ -50,6 +50,7 @@ bool Tag::isEmpty() const
albumartist().isEmpty() && albumartist().isEmpty() &&
artist().isEmpty() && artist().isEmpty() &&
album().isEmpty() && album().isEmpty() &&
unsyncedlyrics().isEmpty() &&
comment().isEmpty() && comment().isEmpty() &&
genre().isEmpty() && genre().isEmpty() &&
year() == 0 && year() == 0 &&
@ -68,6 +69,8 @@ PropertyMap Tag::properties() const
map["ARTIST"].append(artist()); map["ARTIST"].append(artist());
if(!(album().isEmpty())) if(!(album().isEmpty()))
map["ALBUM"].append(album()); map["ALBUM"].append(album());
if(!(unsyncedlyrics().isEmpty()))
map["UNSYNCEDLYRICS"].append(unsyncedlyrics());
if(!(comment().isEmpty())) if(!(comment().isEmpty()))
map["COMMENT"].append(comment()); map["COMMENT"].append(comment());
if(!(genre().isEmpty())) if(!(genre().isEmpty()))
@ -119,6 +122,18 @@ PropertyMap Tag::setProperties(const PropertyMap &origProps)
} else } else
setAlbum(String()); 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")) { if(properties.contains("COMMENT")) {
setComment(properties["COMMENT"].front()); setComment(properties["COMMENT"].front());
oneValueSet.append("COMMENT"); oneValueSet.append("COMMENT");
@ -185,6 +200,7 @@ void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static
target->setAlbumArtist(source->albumartist()); target->setAlbumArtist(source->albumartist());
target->setArtist(source->artist()); target->setArtist(source->artist());
target->setAlbum(source->album()); target->setAlbum(source->album());
target->setUnsyncedlyrics(source->unsyncedlyrics());
target->setComment(source->comment()); target->setComment(source->comment());
target->setGenre(source->genre()); target->setGenre(source->genre());
target->setYear(source->year()); target->setYear(source->year());
@ -200,6 +216,8 @@ void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static
target->setArtist(source->artist()); target->setArtist(source->artist());
if(target->album().isEmpty()) if(target->album().isEmpty())
target->setAlbum(source->album()); target->setAlbum(source->album());
if(target->unsyncedlyrics().isEmpty())
target->setUnsyncedlyrics(source->unsyncedlyrics());
if(target->comment().isEmpty()) if(target->comment().isEmpty())
target->setComment(source->comment()); target->setComment(source->comment());
if(target->genre().isEmpty()) if(target->genre().isEmpty())

View File

@ -102,6 +102,12 @@ namespace TagLib {
*/ */
virtual String album() const = 0; 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 * Returns the track comment; if no comment is present in the tag
* String::null will be returned. * String::null will be returned.
@ -191,6 +197,12 @@ namespace TagLib {
*/ */
virtual void setAlbum(const String &s) = 0; 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 * Sets the comment to \a s. If \a s is String::null then this value will be
* cleared. * cleared.

View File

@ -186,6 +186,11 @@ String TagUnion::album() const
stringUnion(album); stringUnion(album);
} }
String TagUnion::unsyncedlyrics() const
{
stringUnion(unsyncedlyrics);
}
String TagUnion::comment() const String TagUnion::comment() const
{ {
stringUnion(comment); stringUnion(comment);
@ -261,6 +266,11 @@ void TagUnion::setAlbum(const String &s)
setUnion(Album, s); setUnion(Album, s);
} }
void TagUnion::setUnsyncedlyrics(const String &s)
{
setUnion(Unsyncedlyrics, s);
}
void TagUnion::setComment(const String &s) void TagUnion::setComment(const String &s)
{ {
setUnion(Comment, s); setUnion(Comment, s);

View File

@ -63,6 +63,7 @@ namespace TagLib {
virtual String albumartist() const; virtual String albumartist() const;
virtual String artist() const; virtual String artist() const;
virtual String album() const; virtual String album() const;
virtual String unsyncedlyrics() const;
virtual String comment() const; virtual String comment() const;
virtual String genre() const; virtual String genre() const;
virtual unsigned int year() const; virtual unsigned int year() const;
@ -79,6 +80,7 @@ namespace TagLib {
virtual void setAlbumArtist(const String &s); virtual void setAlbumArtist(const String &s);
virtual void setArtist(const String &s); virtual void setArtist(const String &s);
virtual void setAlbum(const String &s); virtual void setAlbum(const String &s);
virtual void setUnsyncedlyrics(const String &s);
virtual void setComment(const String &s); virtual void setComment(const String &s);
virtual void setGenre(const String &s); virtual void setGenre(const String &s);
virtual void setYear(unsigned int i); virtual void setYear(unsigned int i);

View File

@ -61,6 +61,7 @@ namespace TagLib {
* - ORIGINALDATE * - ORIGINALDATE
* - GENRE * - GENRE
* - COMMENT * - COMMENT
* - UNSYNCEDLYRICS
* *
* Sort names: * Sort names:
* *