1230
1363
return getTagFormat(m_tagV2);
1234
* Clean up static resources.
1236
void TagLibFile::staticCleanup()
1238
delete s_tagLibFrameList;
1239
s_tagLibFrameList = 0;
1367
/** Types and descriptions for id3lib frame IDs */
1368
static const struct TypeStrOfId {
1373
{ Frame::FT_Other, I18N_NOOP("AENC - Audio encryption"), false },
1374
{ Frame::FT_Other, I18N_NOOP("APIC - Attached picture"), true },
1375
{ Frame::FT_Other, I18N_NOOP("ASPI - Audio seek point index"), false },
1376
{ Frame::FT_Comment, I18N_NOOP("COMM - Comments"), true },
1377
{ Frame::FT_Other, I18N_NOOP("COMR - Commercial"), false },
1378
{ Frame::FT_Other, I18N_NOOP("ENCR - Encryption method registration"), false },
1379
{ Frame::FT_Other, I18N_NOOP("EQU2 - Equalisation (2)"), false },
1380
{ Frame::FT_Other, I18N_NOOP("ETCO - Event timing codes"), false },
1381
{ Frame::FT_Other, I18N_NOOP("GEOB - General encapsulated object"), true },
1382
{ Frame::FT_Other, I18N_NOOP("GRID - Group identification registration"), false },
1383
{ Frame::FT_Other, I18N_NOOP("LINK - Linked information"), false },
1384
{ Frame::FT_Other, I18N_NOOP("MCDI - Music CD identifier"), false },
1385
{ Frame::FT_Other, I18N_NOOP("MLLT - MPEG location lookup table"), false },
1386
{ Frame::FT_Other, I18N_NOOP("OWNE - Ownership frame"), false },
1387
{ Frame::FT_Other, I18N_NOOP("PRIV - Private frame"), false },
1388
{ Frame::FT_Other, I18N_NOOP("PCNT - Play counter"), false },
1389
{ Frame::FT_Other, I18N_NOOP("POPM - Popularimeter"), false },
1390
{ Frame::FT_Other, I18N_NOOP("POSS - Position synchronisation frame"), false },
1391
{ Frame::FT_Other, I18N_NOOP("RBUF - Recommended buffer size"), false },
1392
{ Frame::FT_Other, I18N_NOOP("RVA2 - Relative volume adjustment (2)"), false },
1393
{ Frame::FT_Other, I18N_NOOP("RVRB - Reverb"), false },
1394
{ Frame::FT_Other, I18N_NOOP("SEEK - Seek frame"), false },
1395
{ Frame::FT_Other, I18N_NOOP("SIGN - Signature frame"), false },
1396
{ Frame::FT_Other, I18N_NOOP("SYLT - Synchronized lyric/text"), false },
1397
{ Frame::FT_Other, I18N_NOOP("SYTC - Synchronized tempo codes"), false },
1398
{ Frame::FT_Album, I18N_NOOP("TALB - Album/Movie/Show title"), true },
1399
{ Frame::FT_Bpm, I18N_NOOP("TBPM - BPM (beats per minute)"), true },
1400
{ Frame::FT_Composer, I18N_NOOP("TCOM - Composer"), true },
1401
{ Frame::FT_Genre, I18N_NOOP("TCON - Content type"), true },
1402
{ Frame::FT_Copyright, I18N_NOOP("TCOP - Copyright message"), true },
1403
{ Frame::FT_Other, I18N_NOOP("TDEN - Encoding time"), true },
1404
{ Frame::FT_Other, I18N_NOOP("TDLY - Playlist delay"), true },
1405
{ Frame::FT_OriginalDate, I18N_NOOP("TDOR - Original release time"), true },
1406
{ Frame::FT_Date, I18N_NOOP("TDRC - Recording time"), true },
1407
{ Frame::FT_Other, I18N_NOOP("TDRL - Release time"), true },
1408
{ Frame::FT_Other, I18N_NOOP("TDTG - Tagging time"), true },
1409
{ Frame::FT_EncodedBy, I18N_NOOP("TENC - Encoded by"), true },
1410
{ Frame::FT_Lyricist, I18N_NOOP("TEXT - Lyricist/Text writer"), true },
1411
{ Frame::FT_Other, I18N_NOOP("TFLT - File type"), true },
1412
{ Frame::FT_Other, I18N_NOOP("TIPL - Involved people list"), true },
1413
{ Frame::FT_Other, I18N_NOOP("TIT1 - Content group description"), true },
1414
{ Frame::FT_Title, I18N_NOOP("TIT2 - Title/songname/content description"), true },
1415
{ Frame::FT_Subtitle, I18N_NOOP("TIT3 - Subtitle/Description refinement"), true },
1416
{ Frame::FT_Other, I18N_NOOP("TKEY - Initial key"), true },
1417
{ Frame::FT_Language, I18N_NOOP("TLAN - Language(s)"), true },
1418
{ Frame::FT_Other, I18N_NOOP("TLEN - Length"), true },
1419
{ Frame::FT_Other, I18N_NOOP("TMCL - Musician credits list"), true },
1420
{ Frame::FT_Other, I18N_NOOP("TMED - Media type"), true },
1421
{ Frame::FT_Other, I18N_NOOP("TMOO - Mood"), true },
1422
{ Frame::FT_OriginalAlbum, I18N_NOOP("TOAL - Original album/movie/show title"), true },
1423
{ Frame::FT_Other, I18N_NOOP("TOFN - Original filename"), true },
1424
{ Frame::FT_Author, I18N_NOOP("TOLY - Original lyricist(s)/text writer(s)"), true },
1425
{ Frame::FT_OriginalArtist, I18N_NOOP("TOPE - Original artist(s)/performer(s)"), true },
1426
{ Frame::FT_Other, I18N_NOOP("TOWN - File owner/licensee"), true },
1427
{ Frame::FT_Artist, I18N_NOOP("TPE1 - Lead performer(s)/Soloist(s)"), true },
1428
{ Frame::FT_Performer, I18N_NOOP("TPE2 - Band/orchestra/accompaniment"), true },
1429
{ Frame::FT_Conductor, I18N_NOOP("TPE3 - Conductor/performer refinement"), true },
1430
{ Frame::FT_Arranger, I18N_NOOP("TPE4 - Interpreted, remixed, or otherwise modified by"), true },
1431
{ Frame::FT_Disc, I18N_NOOP("TPOS - Part of a set"), true },
1432
{ Frame::FT_Other, I18N_NOOP("TPRO - Produced notice"), true },
1433
{ Frame::FT_Publisher, I18N_NOOP("TPUB - Publisher"), true },
1434
{ Frame::FT_Track, I18N_NOOP("TRCK - Track number/Position in set"), true },
1435
{ Frame::FT_Other, I18N_NOOP("TRSN - Internet radio station name"), true },
1436
{ Frame::FT_Other, I18N_NOOP("TRSO - Internet radio station owner"), true },
1437
{ Frame::FT_Other, I18N_NOOP("TSOA - Album sort order"), true },
1438
{ Frame::FT_Other, I18N_NOOP("TSOP - Performer sort order"), true },
1439
{ Frame::FT_Other, I18N_NOOP("TSOT - Title sort order"), true },
1440
{ Frame::FT_Isrc, I18N_NOOP("TSRC - ISRC (international standard recording code)"), true },
1441
{ Frame::FT_Other, I18N_NOOP("TSSE - Software/Hardware and settings used for encoding"), true },
1442
{ Frame::FT_Part, I18N_NOOP("TSST - Set subtitle"), true },
1443
{ Frame::FT_Other, I18N_NOOP("TXXX - User defined text information"), true },
1444
{ Frame::FT_Other, I18N_NOOP("UFID - Unique file identifier"), true },
1445
{ Frame::FT_Other, I18N_NOOP("USER - Terms of use"), false },
1446
{ Frame::FT_Other, I18N_NOOP("USLT - Unsynchronized lyric/text transcription"), true },
1447
{ Frame::FT_Other, I18N_NOOP("WCOM - Commercial information"), true },
1448
{ Frame::FT_Other, I18N_NOOP("WCOP - Copyright/Legal information"), true },
1449
{ Frame::FT_Other, I18N_NOOP("WOAF - Official audio file webpage"), true },
1450
{ Frame::FT_Website, I18N_NOOP("WOAR - Official artist/performer webpage"), true },
1451
{ Frame::FT_Other, I18N_NOOP("WOAS - Official audio source webpage"), true },
1452
{ Frame::FT_Other, I18N_NOOP("WORS - Official internet radio station homepage"), true },
1453
{ Frame::FT_Other, I18N_NOOP("WPAY - Payment"), true },
1454
{ Frame::FT_Other, I18N_NOOP("WPUB - Official publisher webpage"), true },
1455
{ Frame::FT_Other, I18N_NOOP("WXXX - User defined URL link"), true }
1459
* Get type and description of frame.
1461
* @param id ID of frame
1462
* @param type the type is returned here
1463
* @param str the description is returned here
1465
static void getTypeStringForFrameId(TagLib::ByteVector id, Frame::Type& type,
1468
static TagLib::Map<TagLib::ByteVector, unsigned> idIndexMap;
1469
if (idIndexMap.isEmpty()) {
1470
for (unsigned i = 0;
1471
i < sizeof(typeStrOfId) / sizeof(typeStrOfId[0]);
1473
idIndexMap.insert(TagLib::ByteVector(typeStrOfId[i].str, 4), i);
1476
if (idIndexMap.contains(id)) {
1477
const TypeStrOfId& ts = typeStrOfId[idIndexMap[id]];
1481
type = Frame::FT_UnknownFrame;
1487
* Get string description starting with 4 bytes ID.
1489
* @param type type of frame
1493
static const char* getStringForType(Frame::Type type)
1495
if (type != Frame::FT_Other) {
1496
for (unsigned i = 0;
1497
i < sizeof(typeStrOfId) / sizeof(typeStrOfId[0]);
1499
const TypeStrOfId& ts = typeStrOfId[i];
1500
if (ts.type == type) {
1509
* Get the fields from a text identification frame.
1511
* @param tFrame text identification frame
1512
* @param fields the fields are appended to this list
1513
* @param type frame type
1515
* @return text representation of fields (Text or URL).
1517
static QString getFieldsFromTextFrame(
1518
const TagLib::ID3v2::TextIdentificationFrame* tFrame,
1519
Frame::FieldList& fields, Frame::Type type)
1523
field.m_id = Frame::Field::ID_TextEnc;
1524
field.m_value = tFrame->textEncoding();
1525
fields.push_back(field);
1527
const TagLib::ID3v2::UserTextIdentificationFrame* txxxFrame;
1530
dynamic_cast<const TagLib::ID3v2::UserTextIdentificationFrame*>(tFrame))
1532
field.m_id = Frame::Field::ID_Description;
1533
field.m_value = TStringToQString(txxxFrame->description());
1534
fields.push_back(field);
1536
TagLib::StringList slText = tFrame->fieldList();
1537
text = slText.size() > 1 ? TStringToQString(slText[1]) : "";
1539
text = TStringToQString(tFrame->toString());
1541
field.m_id = Frame::Field::ID_Text;
1542
if (type == Frame::FT_Genre) {
1543
text = Genres::getNameString(text);
1545
field.m_value = text;
1546
fields.push_back(field);
1552
* Get the fields from an attached picture frame.
1554
* @param apicFrame attached picture frame
1555
* @param fields the fields are appended to this list
1557
* @return text representation of fields (Text or URL).
1559
static QString getFieldsFromApicFrame(
1560
const TagLib::ID3v2::AttachedPictureFrame* apicFrame,
1561
Frame::FieldList& fields)
1565
field.m_id = Frame::Field::ID_TextEnc;
1566
field.m_value = apicFrame->textEncoding();
1567
fields.push_back(field);
1569
// for compatibility with ID3v2.3 id3lib
1570
field.m_id = Frame::Field::ID_ImageFormat;
1571
field.m_value = QString("");
1572
fields.push_back(field);
1574
field.m_id = Frame::Field::ID_MimeType;
1575
field.m_value = TStringToQString(apicFrame->mimeType());
1576
fields.push_back(field);
1578
field.m_id = Frame::Field::ID_PictureType;
1579
field.m_value = apicFrame->type();
1580
fields.push_back(field);
1582
field.m_id = Frame::Field::ID_Description;
1583
text = TStringToQString(apicFrame->description());
1584
field.m_value = text;
1585
fields.push_back(field);
1587
field.m_id = Frame::Field::ID_Data;
1588
TagLib::ByteVector pic = apicFrame->picture();
1590
QCM_duplicate(ba, pic.data(), pic.size());
1592
fields.push_back(field);
1598
* Get the fields from a comments frame.
1600
* @param commFrame comments frame
1601
* @param fields the fields are appended to this list
1603
* @return text representation of fields (Text or URL).
1605
static QString getFieldsFromCommFrame(
1606
const TagLib::ID3v2::CommentsFrame* commFrame, Frame::FieldList& fields)
1610
field.m_id = Frame::Field::ID_TextEnc;
1611
field.m_value = commFrame->textEncoding();
1612
fields.push_back(field);
1614
field.m_id = Frame::Field::ID_Language;
1615
TagLib::ByteVector bvLang = commFrame->language();
1616
field.m_value = QString(QCM_QCString(bvLang.data(), bvLang.size() + 1));
1617
fields.push_back(field);
1619
field.m_id = Frame::Field::ID_Description;
1620
field.m_value = TStringToQString(commFrame->description());
1621
fields.push_back(field);
1623
field.m_id = Frame::Field::ID_Text;
1624
text = TStringToQString(commFrame->toString());
1625
field.m_value = text;
1626
fields.push_back(field);
1632
* Get the fields from a unique file identifier frame.
1634
* @param ufidFrame unique file identifier frame
1635
* @param fields the fields are appended to this list
1637
* @return text representation of fields (Text or URL).
1639
static QString getFieldsFromUfidFrame(
1640
const TagLib::ID3v2::UniqueFileIdentifierFrame* ufidFrame,
1641
Frame::FieldList& fields)
1645
field.m_id = Frame::Field::ID_Owner;
1646
field.m_value = TStringToQString(ufidFrame->owner());
1647
fields.push_back(field);
1649
field.m_id = Frame::Field::ID_Id;
1650
TagLib::ByteVector id = ufidFrame->identifier();
1652
QCM_duplicate(ba, id.data(), id.size());
1654
fields.push_back(field);
1660
* Get the fields from a general encapsulated object frame.
1662
* @param geobFrame general encapsulated object frame
1663
* @param fields the fields are appended to this list
1665
* @return text representation of fields (Text or URL).
1667
static QString getFieldsFromGeobFrame(
1668
const TagLib::ID3v2::GeneralEncapsulatedObjectFrame* geobFrame,
1669
Frame::FieldList& fields)
1673
field.m_id = Frame::Field::ID_TextEnc;
1674
field.m_value = geobFrame->textEncoding();
1675
fields.push_back(field);
1677
field.m_id = Frame::Field::ID_MimeType;
1678
field.m_value = TStringToQString(geobFrame->mimeType());
1679
fields.push_back(field);
1681
field.m_id = Frame::Field::ID_Filename;
1682
field.m_value = TStringToQString(geobFrame->fileName());
1683
fields.push_back(field);
1685
field.m_id = Frame::Field::ID_Description;
1686
text = TStringToQString(geobFrame->description());
1687
field.m_value = text;
1688
fields.push_back(field);
1690
field.m_id = Frame::Field::ID_Data;
1691
TagLib::ByteVector obj = geobFrame->object();
1693
QCM_duplicate(ba, obj.data(), obj.size());
1695
fields.push_back(field);
1701
* Get the fields from a URL link frame.
1703
* @param wFrame URL link frame
1704
* @param fields the fields are appended to this list
1706
* @return text representation of fields (Text or URL).
1708
static QString getFieldsFromUrlFrame(
1709
const TagLib::ID3v2::UrlLinkFrame* wFrame, Frame::FieldList& fields)
1713
field.m_id = Frame::Field::ID_Url;
1714
text = TStringToQString(wFrame->url());
1715
field.m_value = text;
1716
fields.push_back(field);
1722
* Get the fields from a user URL link frame.
1724
* @param wxxxFrame user URL link frame
1725
* @param fields the fields are appended to this list
1727
* @return text representation of fields (Text or URL).
1729
static QString getFieldsFromUserUrlFrame(
1730
const TagLib::ID3v2::UserUrlLinkFrame* wxxxFrame, Frame::FieldList& fields)
1734
field.m_id = Frame::Field::ID_TextEnc;
1735
field.m_value = wxxxFrame->textEncoding();
1736
fields.push_back(field);
1738
field.m_id = Frame::Field::ID_Description;
1739
field.m_value = TStringToQString(wxxxFrame->description());
1740
fields.push_back(field);
1742
field.m_id = Frame::Field::ID_Url;
1743
text = TStringToQString(wxxxFrame->url());
1744
field.m_value = text;
1745
fields.push_back(field);
1751
* Get the fields from an unsynchronized lyrics frame.
1752
* This is copy-pasted from editCommFrame().
1754
* @param usltFrame unsynchronized frame
1755
* @param fields the fields are appended to this list
1757
* @return text representation of fields (Text or URL).
1759
static QString getFieldsFromUsltFrame(
1760
const TagLib::ID3v2::UnsynchronizedLyricsFrame* usltFrame,
1761
Frame::FieldList& fields)
1765
field.m_id = Frame::Field::ID_TextEnc;
1766
field.m_value = usltFrame->textEncoding();
1767
fields.push_back(field);
1769
field.m_id = Frame::Field::ID_Language;
1770
TagLib::ByteVector bvLang = usltFrame->language();
1771
field.m_value = QString(QCM_QCString(bvLang.data(), bvLang.size() + 1));
1772
fields.push_back(field);
1774
field.m_id = Frame::Field::ID_Description;
1775
field.m_value = TStringToQString(usltFrame->description());
1776
fields.push_back(field);
1778
field.m_id = Frame::Field::ID_Text;
1779
text = TStringToQString(usltFrame->toString());
1780
field.m_value = text;
1781
fields.push_back(field);
1787
* Get the fields from an unknown frame.
1789
* @param unknownFrame unknown frame
1790
* @param fields the fields are appended to this list
1792
* @return text representation of fields (Text or URL).
1794
static QString getFieldsFromUnknownFrame(
1795
const TagLib::ID3v2::Frame* unknownFrame, Frame::FieldList& fields)
1798
field.m_id = Frame::Field::ID_Data;
1799
TagLib::ByteVector dat = unknownFrame->render();
1801
QCM_duplicate(ba, dat.data(), dat.size());
1803
fields.push_back(field);
1808
* Get the fields from an ID3v2 tag.
1810
* @param frame frame
1811
* @param fields the fields are appended to this list
1812
* @param type frame type
1814
* @return text representation of fields (Text or URL).
1816
static QString getFieldsFromId3Frame(const TagLib::ID3v2::Frame* frame,
1817
Frame::FieldList& fields, Frame::Type type)
1820
const TagLib::ID3v2::TextIdentificationFrame* tFrame;
1821
const TagLib::ID3v2::AttachedPictureFrame* apicFrame;
1822
const TagLib::ID3v2::CommentsFrame* commFrame;
1823
const TagLib::ID3v2::UniqueFileIdentifierFrame* ufidFrame;
1824
const TagLib::ID3v2::GeneralEncapsulatedObjectFrame* geobFrame;
1825
const TagLib::ID3v2::UserUrlLinkFrame* wxxxFrame;
1826
const TagLib::ID3v2::UrlLinkFrame* wFrame;
1827
const TagLib::ID3v2::UnsynchronizedLyricsFrame* usltFrame;
1829
dynamic_cast<const TagLib::ID3v2::TextIdentificationFrame*>(frame)) !=
1831
return getFieldsFromTextFrame(tFrame, fields, type);
1832
} else if ((apicFrame =
1833
dynamic_cast<const TagLib::ID3v2::AttachedPictureFrame*>(frame))
1835
return getFieldsFromApicFrame(apicFrame, fields);
1836
} else if ((commFrame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(
1838
return getFieldsFromCommFrame(commFrame, fields);
1839
} else if ((ufidFrame =
1840
dynamic_cast<const TagLib::ID3v2::UniqueFileIdentifierFrame*>(
1842
return getFieldsFromUfidFrame(ufidFrame, fields);
1843
} else if ((geobFrame =
1844
dynamic_cast<const TagLib::ID3v2::GeneralEncapsulatedObjectFrame*>(
1846
return getFieldsFromGeobFrame(geobFrame, fields);
1847
} else if ((wxxxFrame = dynamic_cast<const TagLib::ID3v2::UserUrlLinkFrame*>(
1849
return getFieldsFromUserUrlFrame(wxxxFrame, fields);
1850
} else if ((wFrame = dynamic_cast<const TagLib::ID3v2::UrlLinkFrame*>(
1852
return getFieldsFromUrlFrame(wFrame, fields);
1853
} else if ((usltFrame = dynamic_cast<const TagLib::ID3v2::UnsynchronizedLyricsFrame*>(
1855
return getFieldsFromUsltFrame(usltFrame, fields);
1857
TagLib::ByteVector id = frame->frameID();
1858
#ifndef TAGLIB_SUPPORTS_URLLINK_FRAMES
1859
if (id.startsWith("WXXX")) {
1860
TagLib::ID3v2::UserUrlLinkFrame userUrlLinkFrame(frame->render());
1861
return getFieldsFromUserUrlFrame(&userUrlLinkFrame, fields);
1862
} else if (id.startsWith("W")) {
1863
TagLib::ID3v2::UrlLinkFrame urlLinkFrame(frame->render());
1864
return getFieldsFromUrlFrame(&urlLinkFrame, fields);
1867
#ifndef TAGLIB_SUPPORTS_USLT_FRAMES
1868
if (id.startsWith("USLT")) {
1869
TagLib::ID3v2::UnsynchronizedLyricsFrame usltFrame(frame->render());
1870
return getFieldsFromUsltFrame(&usltFrame, fields);
1873
#ifndef TAGLIB_SUPPORTS_GEOB_FRAMES
1874
if (id.startsWith("GEOB")) {
1875
TagLib::ID3v2::GeneralEncapsulatedObjectFrame geobFrame(frame->render());
1876
return getFieldsFromGeobFrame(&geobFrame, fields);
1879
return getFieldsFromUnknownFrame(frame, fields);
1886
* Convert a string to a language code byte vector.
1888
* @param str string containing language code.
1890
* @return 3 byte vector with language code.
1892
static TagLib::ByteVector languageCodeByteVector(QString str)
1894
uint len = str.length();
1897
} else if (len < 3) {
1898
for (uint i = len; i < 3; ++i) {
1902
return TagLib::ByteVector(str.QCM_latin1(), str.length());
1906
* The follwoing template functions are used to uniformly set fields
1907
* in the different ID3v2 frames.
1910
void setTextEncoding(T*, TagLib::String::Type) {}
1913
void setTextEncoding(TagLib::ID3v2::TextIdentificationFrame* f,
1914
TagLib::String::Type enc)
1916
f->setTextEncoding(enc);
1920
void setTextEncoding(TagLib::ID3v2::AttachedPictureFrame* f,
1921
TagLib::String::Type enc)
1923
f->setTextEncoding(enc);
1927
void setTextEncoding(TagLib::ID3v2::CommentsFrame* f,
1928
TagLib::String::Type enc)
1930
f->setTextEncoding(enc);
1934
void setTextEncoding(TagLib::ID3v2::GeneralEncapsulatedObjectFrame* f,
1935
TagLib::String::Type enc)
1937
f->setTextEncoding(enc);
1941
void setTextEncoding(TagLib::ID3v2::UserUrlLinkFrame* f,
1942
TagLib::String::Type enc)
1944
f->setTextEncoding(enc);
1948
void setTextEncoding(TagLib::ID3v2::UnsynchronizedLyricsFrame* f,
1949
TagLib::String::Type enc)
1951
f->setTextEncoding(enc);
1956
void setDescription(T*, const Frame::Field&) {}
1959
void setDescription(TagLib::ID3v2::UserTextIdentificationFrame* f,
1960
const Frame::Field& fld)
1962
f->setDescription(QSTRING_TO_TSTRING(fld.m_value.toString()));
1966
void setDescription(TagLib::ID3v2::AttachedPictureFrame* f,
1967
const Frame::Field& fld)
1969
f->setDescription(QSTRING_TO_TSTRING(fld.m_value.toString()));
1973
void setDescription(TagLib::ID3v2::CommentsFrame* f, const Frame::Field& fld)
1975
f->setDescription(QSTRING_TO_TSTRING(fld.m_value.toString()));
1979
void setDescription(TagLib::ID3v2::GeneralEncapsulatedObjectFrame* f,
1980
const Frame::Field& fld)
1982
f->setDescription(QSTRING_TO_TSTRING(fld.m_value.toString()));
1986
void setDescription(TagLib::ID3v2::UserUrlLinkFrame* f, const Frame::Field& fld)
1988
f->setDescription(QSTRING_TO_TSTRING(fld.m_value.toString()));
1992
void setDescription(TagLib::ID3v2::UnsynchronizedLyricsFrame* f,
1993
const Frame::Field& fld)
1995
f->setDescription(QSTRING_TO_TSTRING(fld.m_value.toString()));
1999
void setMimeType(T*, const Frame::Field&) {}
2002
void setMimeType(TagLib::ID3v2::AttachedPictureFrame* f,
2003
const Frame::Field& fld)
2005
f->setMimeType(QSTRING_TO_TSTRING(fld.m_value.toString()));
2009
void setMimeType(TagLib::ID3v2::GeneralEncapsulatedObjectFrame* f,
2010
const Frame::Field& fld)
2012
f->setMimeType(QSTRING_TO_TSTRING(fld.m_value.toString()));
2016
void setPictureType(T*, const Frame::Field&) {}
2019
void setPictureType(TagLib::ID3v2::AttachedPictureFrame* f,
2020
const Frame::Field& fld)
2023
static_cast<TagLib::ID3v2::AttachedPictureFrame::Type>(
2024
fld.m_value.toInt()));
2028
void setData(T*, const Frame::Field&) {}
2031
void setData(TagLib::ID3v2::Frame* f, const Frame::Field& fld)
2033
QByteArray ba(fld.m_value.toByteArray());
2034
f->setData(TagLib::ByteVector(ba.data(), ba.size()));
2038
void setData(TagLib::ID3v2::AttachedPictureFrame* f, const Frame::Field& fld)
2040
QByteArray ba(fld.m_value.toByteArray());
2041
f->setPicture(TagLib::ByteVector(ba.data(), ba.size()));
2045
void setData(TagLib::ID3v2::GeneralEncapsulatedObjectFrame* f,
2046
const Frame::Field& fld)
2048
QByteArray ba(fld.m_value.toByteArray());
2049
f->setObject(TagLib::ByteVector(ba.data(), ba.size()));
2053
void setLanguage(T*, const Frame::Field&) {}
2056
void setLanguage(TagLib::ID3v2::CommentsFrame* f, const Frame::Field& fld)
2058
f->setLanguage(languageCodeByteVector(fld.m_value.toString()));
2062
void setLanguage(TagLib::ID3v2::UnsynchronizedLyricsFrame* f,
2063
const Frame::Field& fld)
2065
f->setLanguage(languageCodeByteVector(fld.m_value.toString()));
2069
void setOwner(T*, const Frame::Field&) {}
2072
void setOwner(TagLib::ID3v2::UniqueFileIdentifierFrame* f,
2073
const Frame::Field& fld)
2075
f->setOwner(QSTRING_TO_TSTRING(fld.m_value.toString()));
2079
void setIdentifier(T*, const Frame::Field&) {}
2082
void setIdentifier(TagLib::ID3v2::UniqueFileIdentifierFrame* f,
2083
const Frame::Field& fld)
2085
QByteArray ba(fld.m_value.toByteArray());
2086
f->setIdentifier(TagLib::ByteVector(ba.data(), ba.size()));
2090
void setFilename(T*, const Frame::Field&) {}
2093
void setFilename(TagLib::ID3v2::GeneralEncapsulatedObjectFrame* f,
2094
const Frame::Field& fld)
2096
f->setFileName(QSTRING_TO_TSTRING(fld.m_value.toString()));
2100
void setUrl(T*, const Frame::Field&) {}
2103
void setUrl(TagLib::ID3v2::UrlLinkFrame* f, const Frame::Field& fld)
2105
f->setUrl(QSTRING_TO_TSTRING(fld.m_value.toString()));
2109
void setUrl(TagLib::ID3v2::UserUrlLinkFrame* f, const Frame::Field& fld)
2111
f->setUrl(QSTRING_TO_TSTRING(fld.m_value.toString()));
2115
void setValue(T* f, const TagLib::String& text)
2121
void setValue(TagLib::ID3v2::AttachedPictureFrame* f, const TagLib::String& text)
2123
f->setDescription(text);
2127
* Set the fields in a TagLib ID3v2 frame.
2129
* @param tFrame TagLib frame to set
2130
* @param frame frame with field values
2133
void setTagLibFrame(const TagLibFile* self, T* tFrame, const Frame& frame)
2135
// If value is changed or field list is empty,
2136
// set from value, else from FieldList.
2137
if (frame.isValueChanged() || frame.getFieldList().empty()) {
2138
QString text(frame.getValue());
2139
if (frame.getType() == Frame::FT_Genre) {
2140
text = Genres::getNumberString(text, false);
2141
} else if (frame.getType() == Frame::FT_Track) {
2142
self->addTotalNumberOfTracksIfEnabled(text);
2144
setValue(tFrame, QSTRING_TO_TSTRING(text));
2145
setTextEncoding(tFrame, getTextEncodingConfig(needsUnicode(text)));
2147
for (Frame::FieldList::const_iterator fldIt = frame.getFieldList().begin();
2148
fldIt != frame.getFieldList().end();
2150
const Frame::Field& fld = *fldIt;
2152
case Frame::Field::ID_Text:
2154
QString value(fld.m_value.toString());
2155
if (frame.getType() == Frame::FT_Genre) {
2156
value = Genres::getNumberString(value, false);
2157
} else if (frame.getType() == Frame::FT_Track) {
2158
self->addTotalNumberOfTracksIfEnabled(value);
2160
tFrame->setText(QSTRING_TO_TSTRING(value));
2163
case Frame::Field::ID_TextEnc:
2164
setTextEncoding(tFrame, static_cast<TagLib::String::Type>(
2165
fld.m_value.toInt()));
2167
case Frame::Field::ID_Description:
2168
setDescription(tFrame, fld);
2170
case Frame::Field::ID_MimeType:
2171
setMimeType(tFrame, fld);
2173
case Frame::Field::ID_PictureType:
2174
setPictureType(tFrame, fld);
2176
case Frame::Field::ID_Data:
2177
setData(tFrame, fld);
2179
case Frame::Field::ID_Language:
2180
setLanguage(tFrame, fld);
2182
case Frame::Field::ID_Owner:
2183
setOwner(tFrame, fld);
2185
case Frame::Field::ID_Id:
2186
setIdentifier(tFrame, fld);
2188
case Frame::Field::ID_Filename:
2189
setFilename(tFrame, fld);
2191
case Frame::Field::ID_Url:
2192
setUrl(tFrame, fld);
2200
* Modify an ID3v2 frame.
2202
* @param id3Frame original ID3v2 frame
2203
* @param frame frame with fields to set in new frame
2205
void TagLibFile::setId3v2Frame(
2206
TagLib::ID3v2::Frame* id3Frame, const Frame& frame) const
2209
TagLib::ID3v2::TextIdentificationFrame* tFrame;
2210
TagLib::ID3v2::AttachedPictureFrame* apicFrame;
2211
TagLib::ID3v2::CommentsFrame* commFrame;
2212
TagLib::ID3v2::UniqueFileIdentifierFrame* ufidFrame;
2213
TagLib::ID3v2::GeneralEncapsulatedObjectFrame* geobFrame;
2214
TagLib::ID3v2::UserUrlLinkFrame* wxxxFrame;
2215
TagLib::ID3v2::UrlLinkFrame* wFrame;
2216
TagLib::ID3v2::UnsynchronizedLyricsFrame* usltFrame;
2218
dynamic_cast<TagLib::ID3v2::TextIdentificationFrame*>(id3Frame))
2220
TagLib::ID3v2::UserTextIdentificationFrame* txxxFrame =
2221
dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame*>(id3Frame);
2223
setTagLibFrame(this, txxxFrame, frame);
2225
setTagLibFrame(this, tFrame, frame);
2227
} else if ((apicFrame =
2228
dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(id3Frame))
2230
setTagLibFrame(this, apicFrame, frame);
2231
} else if ((commFrame = dynamic_cast<TagLib::ID3v2::CommentsFrame*>(
2233
setTagLibFrame(this, commFrame, frame);
2234
} else if ((ufidFrame =
2235
dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*>(
2237
setTagLibFrame(this, ufidFrame, frame);
2238
} else if ((geobFrame =
2239
dynamic_cast<TagLib::ID3v2::GeneralEncapsulatedObjectFrame*>(
2241
setTagLibFrame(this, geobFrame, frame);
2242
} else if ((wxxxFrame = dynamic_cast<TagLib::ID3v2::UserUrlLinkFrame*>(
2244
setTagLibFrame(this, wxxxFrame, frame);
2245
} else if ((wFrame = dynamic_cast<TagLib::ID3v2::UrlLinkFrame*>(
2247
setTagLibFrame(this, wFrame, frame);
2248
} else if ((usltFrame =
2249
dynamic_cast<TagLib::ID3v2::UnsynchronizedLyricsFrame*>(
2251
setTagLibFrame(this, usltFrame, frame);
2253
TagLib::ByteVector id(id3Frame->frameID());
2254
// create temporary objects for frames not known by TagLib,
2255
// an UnknownFrame copy will be created by the edit method.
2256
#ifndef TAGLIB_SUPPORTS_URLLINK_FRAMES
2257
if (id.startsWith("WXXX")) {
2258
TagLib::ID3v2::UserUrlLinkFrame userUrlLinkFrame(id3Frame->render());
2259
setTagLibFrame(this, &userUrlLinkFrame, frame);
2260
id3Frame->setData(userUrlLinkFrame.render());
2261
} else if (id.startsWith("W")) {
2262
TagLib::ID3v2::UrlLinkFrame urlLinkFrame(id3Frame->render());
2263
setTagLibFrame(this, &urlLinkFrame, frame);
2264
id3Frame->setData(urlLinkFrame.render());
2267
#ifndef TAGLIB_SUPPORTS_USLT_FRAMES
2268
if (id.startsWith("USLT")) {
2269
TagLib::ID3v2::UnsynchronizedLyricsFrame usltFrame(id3Frame->render());
2270
setTagLibFrame(this, &usltFrame, frame);
2271
id3Frame->setData(usltFrame.render());
2274
#ifndef TAGLIB_SUPPORTS_GEOB_FRAMES
2275
if (id.startsWith("GEOB")) {
2276
TagLib::ID3v2::GeneralEncapsulatedObjectFrame geobFrame(id3Frame->render());
2277
setTagLibFrame(this, &geobFrame, frame);
2278
id3Frame->setData(geobFrame.render());
2282
setTagLibFrame(this, id3Frame, frame);
2289
* Set a frame in the tags 2.
2291
* @param frame frame to set
2293
* @return true if ok.
2295
bool TagLibFile::setFrameV2(const Frame& frame)
2297
// If the frame has an index, change that specific frame
2298
int index = frame.getIndex();
2299
if (index != -1 && m_tagV2) {
2300
TagLib::ID3v2::Tag* id3v2Tag;
2301
TagLib::Ogg::XiphComment* oggTag;
2302
TagLib::APE::Tag* apeTag;
2303
if ((id3v2Tag = dynamic_cast<TagLib::ID3v2::Tag*>(m_tagV2)) != 0) {
2304
const TagLib::ID3v2::FrameList& frameList = id3v2Tag->frameList();
2305
if (index < static_cast<int>(frameList.size())) {
2306
// This is a hack. The frameList should not be modified directly.
2307
// However when removing the old frame and adding a new frame,
2308
// the indices of all frames get invalid.
2309
setId3v2Frame(frameList[index], frame);
2312
} else if ((oggTag = dynamic_cast<TagLib::Ogg::XiphComment*>(m_tagV2)) != 0) {
2313
TagLib::String key = QSTRING_TO_TSTRING(frame.getName(true));
2314
TagLib::String value = QSTRING_TO_TSTRING(frame.getValue());
2315
#ifdef TAGLIB_XIPHCOMMENT_REMOVEFIELD_CRASHES
2316
oggTag->addField(key, value, true);
2318
// This will crash because TagLib uses an invalidated iterator
2319
// after calling erase(). I hope this will be fixed in the next
2320
// version. Until then, remove all fields with that key.
2321
oggTag->removeField(key, oldValue);
2322
oggTag->addField(key, value, false);
2324
if (frame.getType() == Frame::FT_Track) {
2325
int numTracks = getTotalNumberOfTracksIfEnabled();
2326
if (numTracks > 0) {
2327
oggTag->addField("TRACKTOTAL", TagLib::String::number(numTracks), true);
2331
} else if ((apeTag = dynamic_cast<TagLib::APE::Tag*>(m_tagV2)) != 0) {
2332
apeTag->addValue(QSTRING_TO_TSTRING(frame.getName(true)),
2333
QSTRING_TO_TSTRING(frame.getValue()));
2338
// Try the superclass method
2339
return TaggedFile::setFrameV2(frame);
2343
* Get name of frame from type.
2349
static const char* getVorbisNameFromType(Frame::Type type)
2351
static const char* const names[] = {
2352
"TITLE", // FT_Title,
2353
"ARTIST", // FT_Artist,
2354
"ALBUM", // FT_Album,
2355
"COMMENT", // FT_Comment,
2357
"TRACKNUMBER", // FT_Track,
2358
"GENRE", // FT_Genre,
2359
// FT_LastV1Frame = FT_Track,
2360
"ARRANGER", // FT_Arranger,
2361
"AUTHOR", // FT_Author,
2363
"COMPOSER", // FT_Composer,
2364
"CONDUCTOR", // FT_Conductor,
2365
"COPYRIGHT", // FT_Copyright,
2366
"DISCNUMBER", // FT_Disc,
2367
"ENCODED-BY", // FT_EncodedBy,
2369
"LANGUAGE", // FT_Language,
2370
"LYRICIST", // FT_Lyricist,
2371
"ORIGINALALBUM", // FT_OriginalAlbum,
2372
"ORIGINALARTIST", // FT_OriginalArtist,
2373
"ORIGINALDATE", // FT_OriginalDate,
2375
"PERFORMER", // FT_Performer,
2376
"PUBLISHER", // FT_Publisher,
2377
"SUBTITLE", // FT_Subtitle,
2378
"WEBSITE", // FT_Website,
2379
// FT_LastFrame = FT_Website
2381
class not_used { int array_size_check[
2382
sizeof(names) / sizeof(names[0]) == Frame::FT_LastFrame + 1
2384
return type <= Frame::FT_LastFrame ? names[type] : "UNKNOWN";
2388
* Get the frame type for a Vorbis name.
2390
* @param name Vorbis tag name
2392
* @return frame type.
2394
static Frame::Type getTypeFromVorbisName(QString name)
2396
static QMap<QString, int> strNumMap;
2397
if (strNumMap.empty()) {
2398
// first time initialization
2399
for (int i = 0; i <= Frame::FT_LastFrame; ++i) {
2400
Frame::Type type = static_cast<Frame::Type>(i);
2401
strNumMap.insert(getVorbisNameFromType(type), type);
2403
strNumMap.insert("DESCRIPTION", Frame::FT_Comment);
2405
QMap<QString, int>::const_iterator it =
2406
strNumMap.find(name.remove(' ').QCM_toUpper());
2407
if (it != strNumMap.end()) {
2408
return static_cast<Frame::Type>(*it);
2410
return Frame::FT_Other;
2414
* Get the frame type for an APE name.
2416
* @param name APE tag name
2418
* @return frame type.
2420
static Frame::Type getTypeFromApeName(const QString& name)
2422
Frame::Type type = getTypeFromVorbisName(name);
2423
if (type == Frame::FT_Other) {
2424
if (name == "YEAR") {
2425
type = Frame::FT_Date;
2426
} else if (name == "TRACK") {
2427
type = Frame::FT_Track;
2428
} else if (name == "ENCODED BY") {
2429
type = Frame::FT_EncodedBy;
2436
* Get internal name of a Vorbis frame.
2438
* @param frame frame
2440
* @return Vorbis key.
2442
static QString getVorbisName(const Frame& frame)
2444
Frame::Type type = frame.getType();
2445
if (type == Frame::FT_Comment) {
2446
return "DESCRIPTION";
2447
} else if (type <= Frame::FT_LastFrame) {
2448
return getVorbisNameFromType(type);
2450
return frame.getName().remove(' ').QCM_toUpper();
2455
* Get internal name of an APE frame.
2457
* @param frame frame
2461
static QString getApeName(const Frame& frame)
2463
Frame::Type type = frame.getType();
2464
if (type == Frame::FT_Date) {
2466
} else if (type == Frame::FT_Track) {
2468
} else if (type <= Frame::FT_LastFrame) {
2469
return getVorbisNameFromType(type);
2471
return frame.getName().QCM_toUpper();
2476
* Add a frame in the tags 2.
2478
* @param frame frame to add, a field list may be added by this method
2480
* @return true if ok.
2482
bool TagLibFile::addFrameV2(Frame& frame)
2484
TagLib::String::Type enc = getDefaultTextEncoding();
2486
if (makeTagV2Settable()) {
2487
TagLib::ID3v2::Tag* id3v2Tag;
2488
TagLib::Ogg::XiphComment* oggTag;
2489
TagLib::APE::Tag* apeTag;
2490
if ((id3v2Tag = dynamic_cast<TagLib::ID3v2::Tag*>(m_tagV2)) != 0) {
2491
QString name = frame.getType() != Frame::FT_Other ?
2492
QString(getStringForType(frame.getType())) :
2494
QString frameId = name;
2495
frameId.truncate(4);
2496
TagLib::ID3v2::Frame* id3Frame = 0;
2497
if (frameId.startsWith("T")) {
2498
if (frameId == "TXXX") {
2499
id3Frame = new TagLib::ID3v2::UserTextIdentificationFrame(enc);
2501
id3Frame = new TagLib::ID3v2::TextIdentificationFrame(
2502
TagLib::ByteVector(frameId.QCM_latin1(), frameId.length()), enc);
2503
id3Frame->setText(""); // is necessary for createFrame() to work
2505
} else if (frameId == "COMM") {
2506
id3Frame = new TagLib::ID3v2::CommentsFrame(enc);
2507
} else if (frameId == "APIC") {
2508
id3Frame = new TagLib::ID3v2::AttachedPictureFrame;
2510
((TagLib::ID3v2::AttachedPictureFrame*)id3Frame)->setTextEncoding(enc);
2512
} else if (frameId == "UFID") {
2513
// the bytevector must not be empty
2514
id3Frame = new TagLib::ID3v2::UniqueFileIdentifierFrame(
2515
TagLib::String(), TagLib::ByteVector(" "));
2516
} else if (frameId == "GEOB") {
2517
id3Frame = new TagLib::ID3v2::GeneralEncapsulatedObjectFrame;
2519
((TagLib::ID3v2::GeneralEncapsulatedObjectFrame*)id3Frame)->setTextEncoding(enc);
2521
} else if (frameId.startsWith("W")) {
2522
if (frameId == "WXXX") {
2523
id3Frame = new TagLib::ID3v2::UserUrlLinkFrame(enc);
2525
id3Frame = new TagLib::ID3v2::UrlLinkFrame(
2526
TagLib::ByteVector(frameId.QCM_latin1(), frameId.length()));
2527
id3Frame->setText("http://"); // is necessary for createFrame() to work
2529
} else if (frameId == "USLT") {
2530
id3Frame = new TagLib::ID3v2::UnsynchronizedLyricsFrame(enc);
2533
if (!frame.fieldList().empty()) {
2534
frame.setValueFromFieldList();
2535
setId3v2Frame(id3Frame, frame);
2538
// freed in Windows DLL => must be allocated in the same DLL
2539
TagLib::ID3v2::Frame* dllAllocatedFrame =
2540
TagLib::ID3v2::FrameFactory::instance()->createFrame(id3Frame->render());
2541
if (dllAllocatedFrame) {
2542
id3v2Tag->addFrame(dllAllocatedFrame);
2545
id3v2Tag->addFrame(id3Frame);
2547
frame.setInternalName(name);
2548
frame.setIndex(id3v2Tag->frameList().size() - 1);
2549
if (frame.fieldList().empty()) {
2550
// add field list to frame
2551
getFieldsFromId3Frame(id3Frame, frame.fieldList(), frame.getType());
2552
frame.setFieldListFromValue();
2560
} else if ((oggTag = dynamic_cast<TagLib::Ogg::XiphComment*>(m_tagV2)) != 0) {
2561
QString name(getVorbisName(frame));
2562
TagLib::String tname = QSTRING_TO_TSTRING(name);
2563
oggTag->addField(tname, QSTRING_TO_TSTRING(frame.getValue()));
2564
frame.setInternalName(name);
2566
const TagLib::Ogg::FieldListMap& fieldListMap = oggTag->fieldListMap();
2569
for (TagLib::Ogg::FieldListMap::ConstIterator it = fieldListMap.begin();
2570
it != fieldListMap.end();
2572
if ((*it).first == tname) {
2573
index += (*it).second.size() - 1;
2579
frame.setIndex(found ? index : -1);
2582
} else if ((apeTag = dynamic_cast<TagLib::APE::Tag*>(m_tagV2)) != 0) {
2583
QString name(getApeName(frame));
2584
TagLib::String tname = QSTRING_TO_TSTRING(name);
2585
TagLib::String tvalue = QSTRING_TO_TSTRING(frame.getValue());
2586
if (tvalue.isEmpty()) {
2587
tvalue = " "; // empty values are not added by TagLib
2589
apeTag->addValue(tname, tvalue, true);
2590
frame.setInternalName(name);
2592
const TagLib::APE::ItemListMap& itemListMap = apeTag->itemListMap();
2595
for (TagLib::APE::ItemListMap::ConstIterator it = itemListMap.begin();
2596
it != itemListMap.end();
2598
if ((*it).first == tname) {
2604
frame.setIndex(found ? index : -1);
2610
// Try the superclass method
2611
return TaggedFile::addFrameV2(frame);
2615
* Delete a frame in the tags 2.
2617
* @param frame frame to delete.
2619
* @return true if ok.
2621
bool TagLibFile::deleteFrameV2(const Frame& frame)
2623
// If the frame has an index, delete that specific frame
2624
int index = frame.getIndex();
2625
if (index != -1 && m_tagV2) {
2626
TagLib::ID3v2::Tag* id3v2Tag;
2627
TagLib::Ogg::XiphComment* oggTag;
2628
TagLib::APE::Tag* apeTag;
2629
if ((id3v2Tag = dynamic_cast<TagLib::ID3v2::Tag*>(m_tagV2)) != 0) {
2630
const TagLib::ID3v2::FrameList& frameList = id3v2Tag->frameList();
2631
if (index < static_cast<int>(frameList.size())) {
2632
id3v2Tag->removeFrame(frameList[index]);
2636
} else if ((oggTag = dynamic_cast<TagLib::Ogg::XiphComment*>(m_tagV2)) != 0) {
2637
TagLib::String key =
2638
QSTRING_TO_TSTRING(frame.getName(true));
2639
#ifdef TAGLIB_XIPHCOMMENT_REMOVEFIELD_CRASHES
2640
oggTag->removeField(key);
2642
// This will crash because TagLib uses an invalidated iterator
2643
// after calling erase(). I hope this will be fixed in the next
2644
// version. Until then, remove all fields with that key.
2645
oggTag->removeField(key, QSTRING_TO_TSTRING(frame.getValue()));
2649
} else if ((apeTag = dynamic_cast<TagLib::APE::Tag*>(m_tagV2)) != 0) {
2650
TagLib::String key = QSTRING_TO_TSTRING(frame.getName(true));
2651
apeTag->removeItem(key);
2657
// Try the superclass method
2658
return TaggedFile::deleteFrameV2(frame);
2662
* Remove ID3v2 frames.
2664
* @param flt filter specifying which frames to remove
2666
void TagLibFile::deleteFramesV2(const FrameFilter& flt)
2669
TagLib::ID3v2::Tag* id3v2Tag;
2670
TagLib::Ogg::XiphComment* oggTag;
2671
TagLib::APE::Tag* apeTag;
2672
if (flt.areAllEnabled()) {
2673
if ((id3v2Tag = dynamic_cast<TagLib::ID3v2::Tag*>(m_tagV2)) != 0) {
2674
const TagLib::ID3v2::FrameList& frameList = id3v2Tag->frameList();
2675
for (TagLib::ID3v2::FrameList::ConstIterator it = frameList.begin();
2676
it != frameList.end();) {
2677
id3v2Tag->removeFrame(*it++, true);
2680
} else if ((oggTag = dynamic_cast<TagLib::Ogg::XiphComment*>(m_tagV2)) !=
2682
const TagLib::Ogg::FieldListMap& fieldListMap = oggTag->fieldListMap();
2683
for (TagLib::Ogg::FieldListMap::ConstIterator it = fieldListMap.begin();
2684
it != fieldListMap.end();) {
2685
oggTag->removeField((*it++).first);
2688
} else if ((apeTag = dynamic_cast<TagLib::APE::Tag*>(m_tagV2)) != 0) {
2689
const TagLib::APE::ItemListMap& itemListMap = apeTag->itemListMap();
2690
for (TagLib::APE::ItemListMap::ConstIterator it = itemListMap.begin();
2691
it != itemListMap.end();) {
2692
apeTag->removeItem((*it++).first);
2696
TaggedFile::deleteFramesV2(flt);
2699
if ((id3v2Tag = dynamic_cast<TagLib::ID3v2::Tag*>(m_tagV2)) != 0) {
2700
const TagLib::ID3v2::FrameList& frameList = id3v2Tag->frameList();
2703
for (TagLib::ID3v2::FrameList::ConstIterator it = frameList.begin();
2704
it != frameList.end();) {
2705
getTypeStringForFrameId((*it)->frameID(), type, name);
2706
if (flt.isEnabled(type, name)) {
2707
id3v2Tag->removeFrame(*it++, true);
2713
} else if ((oggTag = dynamic_cast<TagLib::Ogg::XiphComment*>(m_tagV2)) !=
2715
const TagLib::Ogg::FieldListMap& fieldListMap = oggTag->fieldListMap();
2716
for (TagLib::Ogg::FieldListMap::ConstIterator it = fieldListMap.begin();
2717
it != fieldListMap.end();) {
2718
QString name(TStringToQString((*it).first));
2719
if (flt.isEnabled(getTypeFromVorbisName(name), name)) {
2720
oggTag->removeField((*it++).first);
2726
} else if ((apeTag = dynamic_cast<TagLib::APE::Tag*>(m_tagV2)) != 0) {
2727
const TagLib::APE::ItemListMap& itemListMap = apeTag->itemListMap();
2728
for (TagLib::APE::ItemListMap::ConstIterator it = itemListMap.begin();
2729
it != itemListMap.end();) {
2730
QString name(TStringToQString((*it).first));
2731
if (flt.isEnabled(getTypeFromApeName(name), name)) {
2732
apeTag->removeItem((*it++).first);
2739
TaggedFile::deleteFramesV2(flt);
2746
* Get all frames in tag 2.
2748
* @param frames frame collection to set.
2750
void TagLibFile::getAllFramesV2(FrameCollection& frames)
2754
TagLib::ID3v2::Tag* id3v2Tag;
2755
TagLib::Ogg::XiphComment* oggTag;
2756
TagLib::APE::Tag* apeTag;
2757
if ((id3v2Tag = dynamic_cast<TagLib::ID3v2::Tag*>(m_tagV2)) != 0) {
2758
const TagLib::ID3v2::FrameList& frameList = id3v2Tag->frameList();
2762
for (TagLib::ID3v2::FrameList::ConstIterator it = frameList.begin();
2763
it != frameList.end();
2765
getTypeStringForFrameId((*it)->frameID(), type, name);
2766
Frame frame(type, TStringToQString((*it)->toString()), name, i++);
2767
frame.setValue(getFieldsFromId3Frame(*it, frame.fieldList(), type));
2768
frames.insert(frame);
2770
} else if ((oggTag = dynamic_cast<TagLib::Ogg::XiphComment*>(m_tagV2)) != 0) {
2771
const TagLib::Ogg::FieldListMap& fieldListMap = oggTag->fieldListMap();
2773
for (TagLib::Ogg::FieldListMap::ConstIterator it = fieldListMap.begin();
2774
it != fieldListMap.end();
2776
QString name = TStringToQString((*it).first);
2777
Frame::Type type = getTypeFromVorbisName(name);
2778
TagLib::StringList stringList = (*it).second;
2779
for (TagLib::StringList::ConstIterator slit = stringList.begin();
2780
slit != stringList.end();
2782
frames.insert(Frame(type, TStringToQString(TagLib::String(*slit)),
2786
} else if ((apeTag = dynamic_cast<TagLib::APE::Tag*>(m_tagV2)) != 0) {
2787
const TagLib::APE::ItemListMap& itemListMap = apeTag->itemListMap();
2789
for (TagLib::APE::ItemListMap::ConstIterator it = itemListMap.begin();
2790
it != itemListMap.end();
2792
QString name = TStringToQString((*it).first);
2793
TagLib::StringList values = (*it).second.toStringList();
2794
Frame::Type type = getTypeFromApeName(name);
2796
Frame(type, values.size() > 0 ? TStringToQString(values.front()) : "",
2800
TaggedFile::getAllFramesV2(frames);
2803
frames.addMissingStandardFrames();
2807
* Get a list of frame IDs which can be added.
2809
* @return list with frame IDs.
2811
QStringList TagLibFile::getFrameIds() const
2813
QStringList lst(TaggedFile::getFrameIds());
2814
TagLib::ID3v2::Tag* id3v2Tag;
2815
if ((id3v2Tag = dynamic_cast<TagLib::ID3v2::Tag*>(m_tagV2)) != 0) {
2816
for (unsigned i = 0; i < sizeof(typeStrOfId) / sizeof(typeStrOfId[0]); ++i) {
2817
const TypeStrOfId& ts = typeStrOfId[i];
2818
if (ts.type == Frame::FT_Other && ts.supported && ts.str) {
2823
static const char* const fieldNames[] = {
2854
for (unsigned i = 0; i < sizeof(fieldNames) / sizeof(fieldNames[0]); ++i) {
2855
lst.append(fieldNames[i]);
2862
* Static initialization.
2863
* Registers file types.
2865
void TagLibFile::staticInit()
2867
TagLib::FileRef::addFileTypeResolver(new SpeexFileTypeResolver);
2868
TagLib::FileRef::addFileTypeResolver(new WavPackFileTypeResolver);
2869
TagLib::FileRef::addFileTypeResolver(new TTAFileTypeResolver);
2870
TagLib::FileRef::addFileTypeResolver(new AACFileTypeResolver);
2871
TagLib::FileRef::addFileTypeResolver(new MP2FileTypeResolver);
2875
* Set the default text encoding.
2877
* @param textEnc default text encoding
2879
void TagLibFile::setDefaultTextEncoding(MiscConfig::TextEncoding textEnc)
2881
// Do not use TagLib::ID3v2::FrameFactory::setDefaultTextEncoding(),
2882
// it will change the encoding of existing frames read in, not only
2883
// of newly created frames, which is really not what we want!
2885
case MiscConfig::TE_ISO8859_1:
2886
s_defaultTextEncoding = TagLib::String::Latin1;
2888
case MiscConfig::TE_UTF16:
2889
s_defaultTextEncoding = TagLib::String::UTF16;
2891
case MiscConfig::TE_UTF8:
2893
s_defaultTextEncoding = TagLib::String::UTF8;
2898
* Create an TagLibFile object if it supports the filename's extension.
2900
* @param di directory information
2901
* @param fn filename
2903
* @return tagged file, 0 if type not supported.
2905
TaggedFile* TagLibFile::Resolver::createFile(const DirInfo* di,
2906
const QString& fn) const
2908
QString ext = fn.right(4).QCM_toLower();
2909
if (((ext == ".mp3" || ext == ".mp2" || ext == ".aac")
2911
&& Kid3App::s_miscCfg.m_id3v2Version == MiscConfig::ID3v2_4_0
2914
|| ext == ".mpc" || ext == ".ogg" || ext == "flac"
2915
|| ext == ".spx" || ext == ".tta"
2916
|| ext.right(3) == ".wv")
2917
return new TagLibFile(di, fn);
2923
* Get a list with all extensions supported by TagLibFile.
2925
* @return list of file extensions.
2927
QStringList TagLibFile::Resolver::getSupportedFileExtensions() const
2929
return QStringList() << ".flac" << ".mp3" << ".mpc" << ".ogg" <<
2930
".spx" << ".tta" << ".aac" << ".mp2" << ".wv";
1242
2933
#endif // HAVE_TAGLIB