Write ID3v2.3 genres with multiple references to ID3v1 genres (#988)

As described in id3v2.3.0.txt (4.2.1, TCON), multiple genres are
only possible as references to ID3v1 genres with an optional
refinement as a text. When downgrading multiple genres from
ID3v2.4.0, they are now converted to numbers when possible and
the first genre text without ID3v1 reference is added as a
refinement. The keywords RX and CR are supported too.
This commit is contained in:
Urs Fleisch
2020-12-30 17:02:41 +01:00
parent d602ae483e
commit 3749dd7b75
2 changed files with 41 additions and 1 deletions

View File

@ -597,12 +597,24 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
if(frameTCON) {
StringList genres = frameTCON->fieldList();
String combined;
String genreText;
const bool hasMultipleGenres = genres.size() > 1;
// If there are multiple genres, add them as multiple references to ID3v1
// genres if such a reference exists. The first genre for which no ID3v1
// genre number exists can be finally added as a refinement.
for(StringList::ConstIterator it = genres.begin(); it != genres.end(); ++it) {
bool ok = false;
int number = it->toInt(&ok);
combined += (ok && number >= 0 && number <= 255) ? ('(' + *it + ')') : *it;
if((ok && number >= 0 && number <= 255) || *it == "RX" || *it == "CR")
combined += '(' + *it + ')';
else if(hasMultipleGenres && (number = ID3v1::genreIndex(*it)) != 255)
combined += '(' + String::number(number) + ')';
else if(genreText.isEmpty())
genreText = *it;
}
if(!genreText.isEmpty())
combined += genreText;
frameTCON = new ID3v2::TextIdentificationFrame("TCON", String::Latin1);
frameTCON->setText(combined);