using namespace TagLib;
using namespace ID3v2;
+namespace
+{
+ void updateGenre(TextIdentificationFrame *frame)
+ {
+ StringList fields = frame->fieldList();
+ StringList newfields;
+
+ for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) {
+ String s = *it;
+ int end = s.find(")");
+
+ if(s.startsWith("(") && end > 0) {
+ // "(12)Genre"
+ String text = s.substr(end + 1);
+ bool ok;
+ int number = s.substr(1, end - 1).toInt(&ok);
+ if(ok && number >= 0 && number <= 255 && !(ID3v1::genre(number) == text))
+ newfields.append(s.substr(1, end - 1));
+ if(!text.isEmpty())
+ newfields.append(text);
+ }
+ else {
+ // "Genre" or "12"
+ newfields.append(s);
+ }
+ }
+
+ if(newfields.isEmpty())
+ fields.append(String());
+
+ frame->setText(newfields);
+ }
+}
+
class FrameFactory::FrameFactoryPrivate
{
public:
// protected members
////////////////////////////////////////////////////////////////////////////////
-FrameFactory::FrameFactory()
+FrameFactory::FrameFactory() :
+ d(new FrameFactoryPrivate())
{
- d = new FrameFactoryPrivate;
}
FrameFactory::~FrameFactory()
delete d;
}
+namespace
+{
+ // Frame conversion table ID3v2.2 -> 2.4
+ const char *frameConversion2[][2] = {
+ { "BUF", "RBUF" },
+ { "CNT", "PCNT" },
+ { "COM", "COMM" },
+ { "CRA", "AENC" },
+ { "ETC", "ETCO" },
+ { "GEO", "GEOB" },
+ { "IPL", "TIPL" },
+ { "MCI", "MCDI" },
+ { "MLL", "MLLT" },
+ { "POP", "POPM" },
+ { "REV", "RVRB" },
+ { "SLT", "SYLT" },
+ { "STC", "SYTC" },
+ { "TAL", "TALB" },
+ { "TBP", "TBPM" },
+ { "TCM", "TCOM" },
+ { "TCO", "TCON" },
+ { "TCP", "TCMP" },
+ { "TCR", "TCOP" },
+ { "TDY", "TDLY" },
+ { "TEN", "TENC" },
+ { "TFT", "TFLT" },
+ { "TKE", "TKEY" },
+ { "TLA", "TLAN" },
+ { "TLE", "TLEN" },
+ { "TMT", "TMED" },
+ { "TOA", "TOAL" },
+ { "TOF", "TOFN" },
+ { "TOL", "TOLY" },
+ { "TOR", "TDOR" },
+ { "TOT", "TOAL" },
+ { "TP1", "TPE1" },
+ { "TP2", "TPE2" },
+ { "TP3", "TPE3" },
+ { "TP4", "TPE4" },
+ { "TPA", "TPOS" },
+ { "TPB", "TPUB" },
+ { "TRC", "TSRC" },
+ { "TRD", "TDRC" },
+ { "TRK", "TRCK" },
+ { "TS2", "TSO2" },
+ { "TSA", "TSOA" },
+ { "TSC", "TSOC" },
+ { "TSP", "TSOP" },
+ { "TSS", "TSSE" },
+ { "TST", "TSOT" },
+ { "TT1", "TIT1" },
+ { "TT2", "TIT2" },
+ { "TT3", "TIT3" },
+ { "TXT", "TOLY" },
+ { "TXX", "TXXX" },
+ { "TYE", "TDRC" },
+ { "UFI", "UFID" },
+ { "ULT", "USLT" },
+ { "WAF", "WOAF" },
+ { "WAR", "WOAR" },
+ { "WAS", "WOAS" },
+ { "WCM", "WCOM" },
+ { "WCP", "WCOP" },
+ { "WPB", "WPUB" },
+ { "WXX", "WXXX" },
+
+ // Apple iTunes nonstandard frames
+ { "PCS", "PCST" },
+ { "TCT", "TCAT" },
+ { "TDR", "TDRL" },
+ { "TDS", "TDES" },
+ { "TID", "TGID" },
+ { "WFD", "WFED" },
+ };
+ const size_t frameConversion2Size = sizeof(frameConversion2) / sizeof(frameConversion2[0]);
+
+ // Frame conversion table ID3v2.3 -> 2.4
+ const char *frameConversion3[][2] = {
+ { "TORY", "TDOR" },
+ { "TYER", "TDRC" },
+ { "IPLS", "TIPL" },
+ };
+ const size_t frameConversion3Size = sizeof(frameConversion3) / sizeof(frameConversion3[0]);
+}
+
bool FrameFactory::updateFrame(Frame::Header *header) const
{
- TagLib::ByteVector frameID = header->frameID();
+ const ByteVector frameID = header->frameID();
switch(header->version()) {
// ID3v2.2 only used 3 bytes for the frame ID, so we need to convert all of
// the frames to their 4 byte ID3v2.4 equivalent.
- convertFrame("BUF", "RBUF", header);
- convertFrame("CNT", "PCNT", header);
- convertFrame("COM", "COMM", header);
- convertFrame("CRA", "AENC", header);
- convertFrame("ETC", "ETCO", header);
- convertFrame("GEO", "GEOB", header);
- convertFrame("IPL", "TIPL", header);
- convertFrame("MCI", "MCDI", header);
- convertFrame("MLL", "MLLT", header);
- convertFrame("POP", "POPM", header);
- convertFrame("REV", "RVRB", header);
- convertFrame("SLT", "SYLT", header);
- convertFrame("STC", "SYTC", header);
- convertFrame("TAL", "TALB", header);
- convertFrame("TBP", "TBPM", header);
- convertFrame("TCM", "TCOM", header);
- convertFrame("TCO", "TCON", header);
- convertFrame("TCP", "TCMP", header);
- convertFrame("TCR", "TCOP", header);
- convertFrame("TDY", "TDLY", header);
- convertFrame("TEN", "TENC", header);
- convertFrame("TFT", "TFLT", header);
- convertFrame("TKE", "TKEY", header);
- convertFrame("TLA", "TLAN", header);
- convertFrame("TLE", "TLEN", header);
- convertFrame("TMT", "TMED", header);
- convertFrame("TOA", "TOAL", header);
- convertFrame("TOF", "TOFN", header);
- convertFrame("TOL", "TOLY", header);
- convertFrame("TOR", "TDOR", header);
- convertFrame("TOT", "TOAL", header);
- convertFrame("TP1", "TPE1", header);
- convertFrame("TP2", "TPE2", header);
- convertFrame("TP3", "TPE3", header);
- convertFrame("TP4", "TPE4", header);
- convertFrame("TPA", "TPOS", header);
- convertFrame("TPB", "TPUB", header);
- convertFrame("TRC", "TSRC", header);
- convertFrame("TRD", "TDRC", header);
- convertFrame("TRK", "TRCK", header);
- convertFrame("TS2", "TSO2", header);
- convertFrame("TSA", "TSOA", header);
- convertFrame("TSC", "TSOC", header);
- convertFrame("TSP", "TSOP", header);
- convertFrame("TSS", "TSSE", header);
- convertFrame("TST", "TSOT", header);
- convertFrame("TT1", "TIT1", header);
- convertFrame("TT2", "TIT2", header);
- convertFrame("TT3", "TIT3", header);
- convertFrame("TXT", "TOLY", header);
- convertFrame("TXX", "TXXX", header);
- convertFrame("TYE", "TDRC", header);
- convertFrame("UFI", "UFID", header);
- convertFrame("ULT", "USLT", header);
- convertFrame("WAF", "WOAF", header);
- convertFrame("WAR", "WOAR", header);
- convertFrame("WAS", "WOAS", header);
- convertFrame("WCM", "WCOM", header);
- convertFrame("WCP", "WCOP", header);
- convertFrame("WPB", "WPUB", header);
- convertFrame("WXX", "WXXX", header);
-
- // Apple iTunes nonstandard frames
- convertFrame("PCS", "PCST", header);
- convertFrame("TCT", "TCAT", header);
- convertFrame("TDR", "TDRL", header);
- convertFrame("TDS", "TDES", header);
- convertFrame("TID", "TGID", header);
- convertFrame("WFD", "WFED", header);
+ for(size_t i = 0; i < frameConversion2Size; ++i) {
+ if(frameID == frameConversion2[i][0]) {
+ header->setFrameID(frameConversion2[i][1]);
+ break;
+ }
+ }
break;
}
return false;
}
- convertFrame("TORY", "TDOR", header);
- convertFrame("TYER", "TDRC", header);
- convertFrame("IPLS", "TIPL", header);
+ for(size_t i = 0; i < frameConversion3Size; ++i) {
+ if(frameID == frameConversion3[i][0]) {
+ header->setFrameID(frameConversion3[i][1]);
+ break;
+ }
+ }
break;
}
// This should catch a typo that existed in TagLib up to and including
// version 1.1 where TRDC was used for the year rather than TDRC.
- convertFrame("TRDC", "TDRC", header);
+ if(frameID == "TRDC")
+ header->setFrameID("TDRC");
+
break;
}
return true;
}
-
-////////////////////////////////////////////////////////////////////////////////
-// private members
-////////////////////////////////////////////////////////////////////////////////
-
-void FrameFactory::convertFrame(const char *from, const char *to,
- Frame::Header *header) const
-{
- if(header->frameID() != from)
- return;
-
- // debug("ID3v2.4 no longer supports the frame type " + String(from) + " It has" +
- // "been converted to the type " + String(to) + ".");
-
- header->setFrameID(to);
-}
-
-void FrameFactory::updateGenre(TextIdentificationFrame *frame) const
-{
- StringList fields = frame->fieldList();
- StringList newfields;
-
- for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) {
- String s = *it;
- int end = s.find(")");
-
- if(s.startsWith("(") && end > 0) {
- // "(12)Genre"
- String text = s.substr(end + 1);
- bool ok;
- int number = s.substr(1, end - 1).toInt(&ok);
- if(ok && number >= 0 && number <= 255 && !(ID3v1::genre(number) == text))
- newfields.append(s.substr(1, end - 1));
- if(!text.isEmpty())
- newfields.append(text);
- }
- else {
- // "Genre" or "12"
- newfields.append(s);
- }
- }
-
- if(newfields.isEmpty())
- fields.append(String());
-
- frame->setText(newfields);
-}