]> granicus.if.org Git - taglib/commitdiff
Efficient lookup for the MP4/ASF field name and ID3v1 genre tables.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 19 Nov 2015 07:35:55 +0000 (16:35 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 19 Nov 2015 07:35:55 +0000 (16:35 +0900)
Linear lookup is much faster and memory efficient when an array is very small.

taglib/asf/asftag.cpp
taglib/mp4/mp4tag.cpp
taglib/mpeg/id3v1/id3v1genres.cpp
taglib/mpeg/id3v2/id3v2frame.cpp
tests/test_id3v1.cpp

index bdf3c5dad43caf62ee872dbe0820297c6c9a0561..5b61a02455b38e3f5f8716a69c85cc12b1b94220 100644 (file)
@@ -210,58 +210,64 @@ bool ASF::Tag::isEmpty() const
          d->attributeListMap.isEmpty();
 }
 
-static const char *keyTranslation[][2] = {
-  { "WM/AlbumTitle", "ALBUM" },
-  { "WM/AlbumArtist", "ALBUMARTIST" },
-  { "WM/Composer", "COMPOSER" },
-  { "WM/Writer", "WRITER" },
-  { "WM/Conductor", "CONDUCTOR" },
-  { "WM/ModifiedBy", "REMIXER" },
-  { "WM/Year", "DATE" },
-  { "WM/OriginalReleaseYear", "ORIGINALDATE" },
-  { "WM/Producer", "PRODUCER" },
-  { "WM/ContentGroupDescription", "GROUPING" },
-  { "WM/SubTitle", "SUBTITLE" },
-  { "WM/SetSubTitle", "DISCSUBTITLE" },
-  { "WM/TrackNumber", "TRACKNUMBER" },
-  { "WM/PartOfSet", "DISCNUMBER" },
-  { "WM/Genre", "GENRE" },
-  { "WM/BeatsPerMinute", "BPM" },
-  { "WM/Mood", "MOOD" },
-  { "WM/ISRC", "ISRC" },
-  { "WM/Lyrics", "LYRICS" },
-  { "WM/Media", "MEDIA" },
-  { "WM/Publisher", "LABEL" },
-  { "WM/CatalogNo", "CATALOGNUMBER" },
-  { "WM/Barcode", "BARCODE" },
-  { "WM/EncodedBy", "ENCODEDBY" },
-  { "WM/AlbumSortOrder", "ALBUMSORT" },
-  { "WM/AlbumArtistSortOrder", "ALBUMARTISTSORT" },
-  { "WM/ArtistSortOrder", "ARTISTSORT" },
-  { "WM/TitleSortOrder", "TITLESORT" },
-  { "WM/Script", "SCRIPT" },
-  { "WM/Language", "LANGUAGE" },
-  { "MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID" },
-  { "MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID" },
-  { "MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID" },
-  { "MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
-  { "MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
-  { "MusicBrainz/Work Id", "MUSICBRAINZ_WORKID" },
-  { "MusicIP/PUID", "MUSICIP_PUID" },
-  { "Acoustid/Id", "ACOUSTID_ID" },
-  { "Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT" },
-};
-
-PropertyMap ASF::Tag::properties() const
-{
-  static Map<String, String> keyMap;
-  if(keyMap.isEmpty()) {
-    int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
-    for(int i = 0; i < numKeys; i++) {
-      keyMap[keyTranslation[i][0]] = keyTranslation[i][1];
+namespace
+{
+  const char *keyTranslation[][2] = {
+    { "WM/AlbumTitle", "ALBUM" },
+    { "WM/AlbumArtist", "ALBUMARTIST" },
+    { "WM/Composer", "COMPOSER" },
+    { "WM/Writer", "WRITER" },
+    { "WM/Conductor", "CONDUCTOR" },
+    { "WM/ModifiedBy", "REMIXER" },
+    { "WM/Year", "DATE" },
+    { "WM/OriginalReleaseYear", "ORIGINALDATE" },
+    { "WM/Producer", "PRODUCER" },
+    { "WM/ContentGroupDescription", "GROUPING" },
+    { "WM/SubTitle", "SUBTITLE" },
+    { "WM/SetSubTitle", "DISCSUBTITLE" },
+    { "WM/TrackNumber", "TRACKNUMBER" },
+    { "WM/PartOfSet", "DISCNUMBER" },
+    { "WM/Genre", "GENRE" },
+    { "WM/BeatsPerMinute", "BPM" },
+    { "WM/Mood", "MOOD" },
+    { "WM/ISRC", "ISRC" },
+    { "WM/Lyrics", "LYRICS" },
+    { "WM/Media", "MEDIA" },
+    { "WM/Publisher", "LABEL" },
+    { "WM/CatalogNo", "CATALOGNUMBER" },
+    { "WM/Barcode", "BARCODE" },
+    { "WM/EncodedBy", "ENCODEDBY" },
+    { "WM/AlbumSortOrder", "ALBUMSORT" },
+    { "WM/AlbumArtistSortOrder", "ALBUMARTISTSORT" },
+    { "WM/ArtistSortOrder", "ARTISTSORT" },
+    { "WM/TitleSortOrder", "TITLESORT" },
+    { "WM/Script", "SCRIPT" },
+    { "WM/Language", "LANGUAGE" },
+    { "MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID" },
+    { "MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID" },
+    { "MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID" },
+    { "MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
+    { "MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
+    { "MusicBrainz/Work Id", "MUSICBRAINZ_WORKID" },
+    { "MusicIP/PUID", "MUSICIP_PUID" },
+    { "Acoustid/Id", "ACOUSTID_ID" },
+    { "Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT" },
+  };
+  const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
+
+  String translateKey(const String &key)
+  {
+    for(size_t i = 0; i < keyTranslationSize; ++i) {
+      if(key == keyTranslation[i][0])
+        return keyTranslation[i][1];
     }
+
+    return String();
   }
+}
 
+PropertyMap ASF::Tag::properties() const
+{
   PropertyMap props;
 
   if(!d->title.isEmpty()) {
@@ -279,8 +285,8 @@ PropertyMap ASF::Tag::properties() const
 
   ASF::AttributeListMap::ConstIterator it = d->attributeListMap.begin();
   for(; it != d->attributeListMap.end(); ++it) {
-    if(keyMap.contains(it->first)) {
-      String key = keyMap[it->first];
+    const String key = translateKey(it->first);
+    if(!key.isEmpty()) {
       AttributeList::ConstIterator it2 = it->second.begin();
       for(; it2 != it->second.end(); ++it2) {
         if(key == "TRACKNUMBER") {
index 47c802ce644962f4dde034c697e54b757193b4b5..005c8a4d85aea9fc4ebaa7e74009eb7762f68df9 100644 (file)
@@ -814,70 +814,76 @@ bool MP4::Tag::contains(const String &key) const
   return d->items.contains(key);
 }
 
-static const char *keyTranslation[][2] = {
-  { "\251nam", "TITLE" },
-  { "\251ART", "ARTIST" },
-  { "\251alb", "ALBUM" },
-  { "\251cmt", "COMMENT" },
-  { "\251gen", "GENRE" },
-  { "\251day", "DATE" },
-  { "\251wrt", "COMPOSER" },
-  { "\251grp", "GROUPING" },
-  { "aART", "ALBUMARTIST" },
-  { "trkn", "TRACKNUMBER" },
-  { "disk", "DISCNUMBER" },
-  { "cpil", "COMPILATION" },
-  { "tmpo", "BPM" },
-  { "cprt", "COPYRIGHT" },
-  { "\251lyr", "LYRICS" },
-  { "\251too", "ENCODEDBY" },
-  { "soal", "ALBUMSORT" },
-  { "soaa", "ALBUMARTISTSORT" },
-  { "soar", "ARTISTSORT" },
-  { "sonm", "TITLESORT" },
-  { "soco", "COMPOSERSORT" },
-  { "sosn", "SHOWSORT" },
-  { "----:com.apple.iTunes:MusicBrainz Track Id", "MUSICBRAINZ_TRACKID" },
-  { "----:com.apple.iTunes:MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID" },
-  { "----:com.apple.iTunes:MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID" },
-  { "----:com.apple.iTunes:MusicBrainz Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
-  { "----:com.apple.iTunes:MusicBrainz Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
-  { "----:com.apple.iTunes:MusicBrainz Work Id", "MUSICBRAINZ_WORKID" },
-  { "----:com.apple.iTunes:ASIN", "ASIN" },
-  { "----:com.apple.iTunes:LABEL", "LABEL" },
-  { "----:com.apple.iTunes:LYRICIST", "LYRICIST" },
-  { "----:com.apple.iTunes:CONDUCTOR", "CONDUCTOR" },
-  { "----:com.apple.iTunes:REMIXER", "REMIXER" },
-  { "----:com.apple.iTunes:ENGINEER", "ENGINEER" },
-  { "----:com.apple.iTunes:PRODUCER", "PRODUCER" },
-  { "----:com.apple.iTunes:DJMIXER", "DJMIXER" },
-  { "----:com.apple.iTunes:MIXER", "MIXER" },
-  { "----:com.apple.iTunes:SUBTITLE", "SUBTITLE" },
-  { "----:com.apple.iTunes:DISCSUBTITLE", "DISCSUBTITLE" },
-  { "----:com.apple.iTunes:MOOD", "MOOD" },
-  { "----:com.apple.iTunes:ISRC", "ISRC" },
-  { "----:com.apple.iTunes:CATALOGNUMBER", "CATALOGNUMBER" },
-  { "----:com.apple.iTunes:BARCODE", "BARCODE" },
-  { "----:com.apple.iTunes:SCRIPT", "SCRIPT" },
-  { "----:com.apple.iTunes:LANGUAGE", "LANGUAGE" },
-  { "----:com.apple.iTunes:LICENSE", "LICENSE" },
-  { "----:com.apple.iTunes:MEDIA", "MEDIA" },
-};
+namespace
+{
+  const char *keyTranslation[][2] = {
+    { "\251nam", "TITLE" },
+    { "\251ART", "ARTIST" },
+    { "\251alb", "ALBUM" },
+    { "\251cmt", "COMMENT" },
+    { "\251gen", "GENRE" },
+    { "\251day", "DATE" },
+    { "\251wrt", "COMPOSER" },
+    { "\251grp", "GROUPING" },
+    { "aART", "ALBUMARTIST" },
+    { "trkn", "TRACKNUMBER" },
+    { "disk", "DISCNUMBER" },
+    { "cpil", "COMPILATION" },
+    { "tmpo", "BPM" },
+    { "cprt", "COPYRIGHT" },
+    { "\251lyr", "LYRICS" },
+    { "\251too", "ENCODEDBY" },
+    { "soal", "ALBUMSORT" },
+    { "soaa", "ALBUMARTISTSORT" },
+    { "soar", "ARTISTSORT" },
+    { "sonm", "TITLESORT" },
+    { "soco", "COMPOSERSORT" },
+    { "sosn", "SHOWSORT" },
+    { "----:com.apple.iTunes:MusicBrainz Track Id", "MUSICBRAINZ_TRACKID" },
+    { "----:com.apple.iTunes:MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID" },
+    { "----:com.apple.iTunes:MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID" },
+    { "----:com.apple.iTunes:MusicBrainz Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
+    { "----:com.apple.iTunes:MusicBrainz Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
+    { "----:com.apple.iTunes:MusicBrainz Work Id", "MUSICBRAINZ_WORKID" },
+    { "----:com.apple.iTunes:ASIN", "ASIN" },
+    { "----:com.apple.iTunes:LABEL", "LABEL" },
+    { "----:com.apple.iTunes:LYRICIST", "LYRICIST" },
+    { "----:com.apple.iTunes:CONDUCTOR", "CONDUCTOR" },
+    { "----:com.apple.iTunes:REMIXER", "REMIXER" },
+    { "----:com.apple.iTunes:ENGINEER", "ENGINEER" },
+    { "----:com.apple.iTunes:PRODUCER", "PRODUCER" },
+    { "----:com.apple.iTunes:DJMIXER", "DJMIXER" },
+    { "----:com.apple.iTunes:MIXER", "MIXER" },
+    { "----:com.apple.iTunes:SUBTITLE", "SUBTITLE" },
+    { "----:com.apple.iTunes:DISCSUBTITLE", "DISCSUBTITLE" },
+    { "----:com.apple.iTunes:MOOD", "MOOD" },
+    { "----:com.apple.iTunes:ISRC", "ISRC" },
+    { "----:com.apple.iTunes:CATALOGNUMBER", "CATALOGNUMBER" },
+    { "----:com.apple.iTunes:BARCODE", "BARCODE" },
+    { "----:com.apple.iTunes:SCRIPT", "SCRIPT" },
+    { "----:com.apple.iTunes:LANGUAGE", "LANGUAGE" },
+    { "----:com.apple.iTunes:LICENSE", "LICENSE" },
+    { "----:com.apple.iTunes:MEDIA", "MEDIA" },
+  };
+  const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
+
+  String translateKey(const String &key)
+  {
+    for(size_t i = 0; i < keyTranslationSize; ++i) {
+      if(key == keyTranslation[i][0])
+        return keyTranslation[i][1];
+    }
+
+    return String();
+  }
+}
 
 PropertyMap MP4::Tag::properties() const
 {
-  static Map<String, String> keyMap;
-  if(keyMap.isEmpty()) {
-    int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
-    for(int i = 0; i < numKeys; i++) {
-      keyMap[keyTranslation[i][0]] = keyTranslation[i][1];
-    }
-  }
-
   PropertyMap props;
   for(MP4::ItemMap::ConstIterator it = d->items.begin(); it != d->items.end(); ++it) {
-    if(keyMap.contains(it->first)) {
-      String key = keyMap[it->first];
+    const String key = translateKey(it->first);
+    if(!key.isEmpty()) {
       if(key == "TRACKNUMBER" || key == "DISCNUMBER") {
         MP4::Item::IntPair ip = it->second.toIntPair();
         String value = String::number(ip.first);
index 074c8bff324548e01de319413d9e0cc48a4b23b0..def91910ea86d159555eb86be39f7dadbe87cabf 100644 (file)
 
 using namespace TagLib;
 
-namespace TagLib {
-  namespace ID3v1 {
-
-    static const int genresSize = 192;
-    static const String genres[] = {
-      "Blues",
-      "Classic Rock",
-      "Country",
-      "Dance",
-      "Disco",
-      "Funk",
-      "Grunge",
-      "Hip-Hop",
-      "Jazz",
-      "Metal",
-      "New Age",
-      "Oldies",
-      "Other",
-      "Pop",
-      "R&B",
-      "Rap",
-      "Reggae",
-      "Rock",
-      "Techno",
-      "Industrial",
-      "Alternative",
-      "Ska",
-      "Death Metal",
-      "Pranks",
-      "Soundtrack",
-      "Euro-Techno",
-      "Ambient",
-      "Trip-Hop",
-      "Vocal",
-      "Jazz+Funk",
-      "Fusion",
-      "Trance",
-      "Classical",
-      "Instrumental",
-      "Acid",
-      "House",
-      "Game",
-      "Sound Clip",
-      "Gospel",
-      "Noise",
-      "Alternative Rock",
-      "Bass",
-      "Soul",
-      "Punk",
-      "Space",
-      "Meditative",
-      "Instrumental Pop",
-      "Instrumental Rock",
-      "Ethnic",
-      "Gothic",
-      "Darkwave",
-      "Techno-Industrial",
-      "Electronic",
-      "Pop-Folk",
-      "Eurodance",
-      "Dream",
-      "Southern Rock",
-      "Comedy",
-      "Cult",
-      "Gangsta",
-      "Top 40",
-      "Christian Rap",
-      "Pop/Funk",
-      "Jungle",
-      "Native American",
-      "Cabaret",
-      "New Wave",
-      "Psychedelic",
-      "Rave",
-      "Showtunes",
-      "Trailer",
-      "Lo-Fi",
-      "Tribal",
-      "Acid Punk",
-      "Acid Jazz",
-      "Polka",
-      "Retro",
-      "Musical",
-      "Rock & Roll",
-      "Hard Rock",
-      "Folk",
-      "Folk/Rock",
-      "National Folk",
-      "Swing",
-      "Fusion",
-      "Bebob",
-      "Latin",
-      "Revival",
-      "Celtic",
-      "Bluegrass",
-      "Avantgarde",
-      "Gothic Rock",
-      "Progressive Rock",
-      "Psychedelic Rock",
-      "Symphonic Rock",
-      "Slow Rock",
-      "Big Band",
-      "Chorus",
-      "Easy Listening",
-      "Acoustic",
-      "Humour",
-      "Speech",
-      "Chanson",
-      "Opera",
-      "Chamber Music",
-      "Sonata",
-      "Symphony",
-      "Booty Bass",
-      "Primus",
-      "Porn Groove",
-      "Satire",
-      "Slow Jam",
-      "Club",
-      "Tango",
-      "Samba",
-      "Folklore",
-      "Ballad",
-      "Power Ballad",
-      "Rhythmic Soul",
-      "Freestyle",
-      "Duet",
-      "Punk Rock",
-      "Drum Solo",
-      "A Cappella",
-      "Euro-House",
-      "Dance Hall",
-      "Goa",
-      "Drum & Bass",
-      "Club-House",
-      "Hardcore",
-      "Terror",
-      "Indie",
-      "BritPop",
-      "Negerpunk",
-      "Polsk Punk",
-      "Beat",
-      "Christian Gangsta Rap",
-      "Heavy Metal",
-      "Black Metal",
-      "Crossover",
-      "Contemporary Christian",
-      "Christian Rock",
-      "Merengue",
-      "Salsa",
-      "Thrash Metal",
-      "Anime",
-      "Jpop",
-      "Synthpop",
-      "Abstract",
-      "Art Rock",
-      "Baroque",
-      "Bhangra",
-      "Big Beat",
-      "Breakbeat",
-      "Chillout",
-      "Downtempo",
-      "Dub",
-      "EBM",
-      "Eclectic",
-      "Electro",
-      "Electroclash",
-      "Emo",
-      "Experimental",
-      "Garage",
-      "Global",
-      "IDM",
-      "Illbient",
-      "Industro-Goth",
-      "Jam Band",
-      "Krautrock",
-      "Leftfield",
-      "Lounge",
-      "Math Rock",
-      "New Romantic",
-      "Nu-Breakz",
-      "Post-Punk",
-      "Post-Rock",
-      "Psytrance",
-      "Shoegaze",
-      "Space Rock",
-      "Trop Rock",
-      "World Music",
-      "Neoclassical",
-      "Audiobook",
-      "Audio Theatre",
-      "Neue Deutsche Welle",
-      "Podcast",
-      "Indie Rock",
-      "G-Funk",
-      "Dubstep",
-      "Garage Rock",
-      "Psybient"
-    };
-  }
+namespace
+{
+  const wchar *genres[] = {
+    L"Blues",
+    L"Classic Rock",
+    L"Country",
+    L"Dance",
+    L"Disco",
+    L"Funk",
+    L"Grunge",
+    L"Hip-Hop",
+    L"Jazz",
+    L"Metal",
+    L"New Age",
+    L"Oldies",
+    L"Other",
+    L"Pop",
+    L"R&B",
+    L"Rap",
+    L"Reggae",
+    L"Rock",
+    L"Techno",
+    L"Industrial",
+    L"Alternative",
+    L"Ska",
+    L"Death Metal",
+    L"Pranks",
+    L"Soundtrack",
+    L"Euro-Techno",
+    L"Ambient",
+    L"Trip-Hop",
+    L"Vocal",
+    L"Jazz+Funk",
+    L"Fusion",
+    L"Trance",
+    L"Classical",
+    L"Instrumental",
+    L"Acid",
+    L"House",
+    L"Game",
+    L"Sound Clip",
+    L"Gospel",
+    L"Noise",
+    L"Alternative Rock",
+    L"Bass",
+    L"Soul",
+    L"Punk",
+    L"Space",
+    L"Meditative",
+    L"Instrumental Pop",
+    L"Instrumental Rock",
+    L"Ethnic",
+    L"Gothic",
+    L"Darkwave",
+    L"Techno-Industrial",
+    L"Electronic",
+    L"Pop-Folk",
+    L"Eurodance",
+    L"Dream",
+    L"Southern Rock",
+    L"Comedy",
+    L"Cult",
+    L"Gangsta",
+    L"Top 40",
+    L"Christian Rap",
+    L"Pop/Funk",
+    L"Jungle",
+    L"Native American",
+    L"Cabaret",
+    L"New Wave",
+    L"Psychedelic",
+    L"Rave",
+    L"Showtunes",
+    L"Trailer",
+    L"Lo-Fi",
+    L"Tribal",
+    L"Acid Punk",
+    L"Acid Jazz",
+    L"Polka",
+    L"Retro",
+    L"Musical",
+    L"Rock & Roll",
+    L"Hard Rock",
+    L"Folk",
+    L"Folk/Rock",
+    L"National Folk",
+    L"Swing",
+    L"Fusion",
+    L"Bebob",
+    L"Latin",
+    L"Revival",
+    L"Celtic",
+    L"Bluegrass",
+    L"Avantgarde",
+    L"Gothic Rock",
+    L"Progressive Rock",
+    L"Psychedelic Rock",
+    L"Symphonic Rock",
+    L"Slow Rock",
+    L"Big Band",
+    L"Chorus",
+    L"Easy Listening",
+    L"Acoustic",
+    L"Humour",
+    L"Speech",
+    L"Chanson",
+    L"Opera",
+    L"Chamber Music",
+    L"Sonata",
+    L"Symphony",
+    L"Booty Bass",
+    L"Primus",
+    L"Porn Groove",
+    L"Satire",
+    L"Slow Jam",
+    L"Club",
+    L"Tango",
+    L"Samba",
+    L"Folklore",
+    L"Ballad",
+    L"Power Ballad",
+    L"Rhythmic Soul",
+    L"Freestyle",
+    L"Duet",
+    L"Punk Rock",
+    L"Drum Solo",
+    L"A Cappella",
+    L"Euro-House",
+    L"Dance Hall",
+    L"Goa",
+    L"Drum & Bass",
+    L"Club-House",
+    L"Hardcore",
+    L"Terror",
+    L"Indie",
+    L"BritPop",
+    L"Negerpunk",
+    L"Polsk Punk",
+    L"Beat",
+    L"Christian Gangsta Rap",
+    L"Heavy Metal",
+    L"Black Metal",
+    L"Crossover",
+    L"Contemporary Christian",
+    L"Christian Rock",
+    L"Merengue",
+    L"Salsa",
+    L"Thrash Metal",
+    L"Anime",
+    L"Jpop",
+    L"Synthpop",
+    L"Abstract",
+    L"Art Rock",
+    L"Baroque",
+    L"Bhangra",
+    L"Big Beat",
+    L"Breakbeat",
+    L"Chillout",
+    L"Downtempo",
+    L"Dub",
+    L"EBM",
+    L"Eclectic",
+    L"Electro",
+    L"Electroclash",
+    L"Emo",
+    L"Experimental",
+    L"Garage",
+    L"Global",
+    L"IDM",
+    L"Illbient",
+    L"Industro-Goth",
+    L"Jam Band",
+    L"Krautrock",
+    L"Leftfield",
+    L"Lounge",
+    L"Math Rock",
+    L"New Romantic",
+    L"Nu-Breakz",
+    L"Post-Punk",
+    L"Post-Rock",
+    L"Psytrance",
+    L"Shoegaze",
+    L"Space Rock",
+    L"Trop Rock",
+    L"World Music",
+    L"Neoclassical",
+    L"Audiobook",
+    L"Audio Theatre",
+    L"Neue Deutsche Welle",
+    L"Podcast",
+    L"Indie Rock",
+    L"G-Funk",
+    L"Dubstep",
+    L"Garage Rock",
+    L"Psybient"
+  };
+  const int genresSize = sizeof(genres) / sizeof(genres[0]);
 }
 
 StringList ID3v1::genreList()
 {
-  static StringList l;
-  if(l.isEmpty()) {
-    for(int i = 0; i < genresSize; i++)
-      l.append(genres[i]);
+  StringList l;
+  for(int i = 0; i < genresSize; i++) {
+    l.append(genres[i]);
   }
+
   return l;
 }
 
 ID3v1::GenreMap ID3v1::genreMap()
 {
-  static GenreMap m;
-  if(m.isEmpty()) {
-    for(int i = 0; i < genresSize; i++)
-      m.insert(genres[i], i);
+  GenreMap m;
+  for(int i = 0; i < genresSize; i++) {
+    m.insert(genres[i], i);
   }
+
   return m;
 }
 
 String ID3v1::genre(int i)
 {
   if(i >= 0 && i < genresSize)
-    return genres[i] + String::null; // always make a copy
-  return String::null;
+    return String(genres[i]); // always make a copy
+  else
+    return String();
 }
 
 int ID3v1::genreIndex(const String &name)
 {
-  if(genreMap().contains(name))
-    return genreMap()[name];
+  for(int i = 0; i < genresSize; ++i) {
+    if(name == genres[i])
+      return i;
+  }
+
   return 255;
 }
index 91eec32845f8f2f7916daf5d40c1517efc277a02..1e679780f430bf26909f7236b21977c3b027d53b 100644 (file)
@@ -364,98 +364,101 @@ String::Type Frame::checkTextEncoding(const StringList &fields, String::Type enc
   return checkEncoding(fields, encoding, header()->version());
 }
 
-static const size_t frameTranslationSize = 51;
-static const char *frameTranslation[][2] = {
-  // Text information frames
-  { "TALB", "ALBUM"},
-  { "TBPM", "BPM" },
-  { "TCOM", "COMPOSER" },
-  { "TCON", "GENRE" },
-  { "TCOP", "COPYRIGHT" },
-  { "TDEN", "ENCODINGTIME" },
-  { "TDLY", "PLAYLISTDELAY" },
-  { "TDOR", "ORIGINALDATE" },
-  { "TDRC", "DATE" },
-  // { "TRDA", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
-  // { "TDAT", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
-  // { "TYER", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
-  // { "TIME", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
-  { "TDRL", "RELEASEDATE" },
-  { "TDTG", "TAGGINGDATE" },
-  { "TENC", "ENCODEDBY" },
-  { "TEXT", "LYRICIST" },
-  { "TFLT", "FILETYPE" },
-  //{ "TIPL", "INVOLVEDPEOPLE" }, handled separately
-  { "TIT1", "CONTENTGROUP" },
-  { "TIT2", "TITLE"},
-  { "TIT3", "SUBTITLE" },
-  { "TKEY", "INITIALKEY" },
-  { "TLAN", "LANGUAGE" },
-  { "TLEN", "LENGTH" },
-  //{ "TMCL", "MUSICIANCREDITS" }, handled separately
-  { "TMED", "MEDIA" },
-  { "TMOO", "MOOD" },
-  { "TOAL", "ORIGINALALBUM" },
-  { "TOFN", "ORIGINALFILENAME" },
-  { "TOLY", "ORIGINALLYRICIST" },
-  { "TOPE", "ORIGINALARTIST" },
-  { "TOWN", "OWNER" },
-  { "TPE1", "ARTIST"},
-  { "TPE2", "ALBUMARTIST" }, // id3's spec says 'PERFORMER', but most programs use 'ALBUMARTIST'
-  { "TPE3", "CONDUCTOR" },
-  { "TPE4", "REMIXER" }, // could also be ARRANGER
-  { "TPOS", "DISCNUMBER" },
-  { "TPRO", "PRODUCEDNOTICE" },
-  { "TPUB", "LABEL" },
-  { "TRCK", "TRACKNUMBER" },
-  { "TRSN", "RADIOSTATION" },
-  { "TRSO", "RADIOSTATIONOWNER" },
-  { "TSOA", "ALBUMSORT" },
-  { "TSOP", "ARTISTSORT" },
-  { "TSOT", "TITLESORT" },
-  { "TSO2", "ALBUMARTISTSORT" }, // non-standard, used by iTunes
-  { "TSRC", "ISRC" },
-  { "TSSE", "ENCODING" },
-  // URL frames
-  { "WCOP", "COPYRIGHTURL" },
-  { "WOAF", "FILEWEBPAGE" },
-  { "WOAR", "ARTISTWEBPAGE" },
-  { "WOAS", "AUDIOSOURCEWEBPAGE" },
-  { "WORS", "RADIOSTATIONWEBPAGE" },
-  { "WPAY", "PAYMENTWEBPAGE" },
-  { "WPUB", "PUBLISHERWEBPAGE" },
-  //{ "WXXX", "URL"}, handled specially
-  // Other frames
-  { "COMM", "COMMENT" },
-  //{ "USLT", "LYRICS" }, handled specially
-  // Apple iTunes proprietary frames
-  { "PCST", "PODCAST" },
-  { "TCAT", "PODCASTCATEGORY" },
-  { "TDES", "PODCASTDESC" },
-  { "TGID", "PODCASTID" },
-  { "WFED", "PODCASTURL" },
-};
-
-static const size_t txxxFrameTranslationSize = 8;
-static const char *txxxFrameTranslation[][2] = {
-  { "MUSICBRAINZ ALBUM ID",         "MUSICBRAINZ_ALBUMID" },
-  { "MUSICBRAINZ ARTIST ID",        "MUSICBRAINZ_ARTISTID" },
-  { "MUSICBRAINZ ALBUM ARTIST ID",  "MUSICBRAINZ_ALBUMARTISTID" },
-  { "MUSICBRAINZ RELEASE GROUP ID", "MUSICBRAINZ_RELEASEGROUPID" },
-  { "MUSICBRAINZ WORK ID",          "MUSICBRAINZ_WORKID" },
-  { "ACOUSTID ID",                  "ACOUSTID_ID" },
-  { "ACOUSTID FINGERPRINT",         "ACOUSTID_FINGERPRINT" },
-  { "MUSICIP PUID",                 "MUSICIP_PUID" },
-};
-
-// list of deprecated frames and their successors
-static const size_t deprecatedFramesSize = 4;
-static const char *deprecatedFrames[][2] = {
-  {"TRDA", "TDRC"}, // 2.3 -> 2.4 (http://en.wikipedia.org/wiki/ID3)
-  {"TDAT", "TDRC"}, // 2.3 -> 2.4
-  {"TYER", "TDRC"}, // 2.3 -> 2.4
-  {"TIME", "TDRC"}, // 2.3 -> 2.4
-};
+namespace
+{
+  const char *frameTranslation[][2] = {
+    // Text information frames
+    { "TALB", "ALBUM"},
+    { "TBPM", "BPM" },
+    { "TCOM", "COMPOSER" },
+    { "TCON", "GENRE" },
+    { "TCOP", "COPYRIGHT" },
+    { "TDEN", "ENCODINGTIME" },
+    { "TDLY", "PLAYLISTDELAY" },
+    { "TDOR", "ORIGINALDATE" },
+    { "TDRC", "DATE" },
+    // { "TRDA", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
+    // { "TDAT", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
+    // { "TYER", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
+    // { "TIME", "DATE" }, // id3 v2.3, replaced by TDRC in v2.4
+    { "TDRL", "RELEASEDATE" },
+    { "TDTG", "TAGGINGDATE" },
+    { "TENC", "ENCODEDBY" },
+    { "TEXT", "LYRICIST" },
+    { "TFLT", "FILETYPE" },
+    //{ "TIPL", "INVOLVEDPEOPLE" }, handled separately
+    { "TIT1", "CONTENTGROUP" },
+    { "TIT2", "TITLE"},
+    { "TIT3", "SUBTITLE" },
+    { "TKEY", "INITIALKEY" },
+    { "TLAN", "LANGUAGE" },
+    { "TLEN", "LENGTH" },
+    //{ "TMCL", "MUSICIANCREDITS" }, handled separately
+    { "TMED", "MEDIA" },
+    { "TMOO", "MOOD" },
+    { "TOAL", "ORIGINALALBUM" },
+    { "TOFN", "ORIGINALFILENAME" },
+    { "TOLY", "ORIGINALLYRICIST" },
+    { "TOPE", "ORIGINALARTIST" },
+    { "TOWN", "OWNER" },
+    { "TPE1", "ARTIST"},
+    { "TPE2", "ALBUMARTIST" }, // id3's spec says 'PERFORMER', but most programs use 'ALBUMARTIST'
+    { "TPE3", "CONDUCTOR" },
+    { "TPE4", "REMIXER" }, // could also be ARRANGER
+    { "TPOS", "DISCNUMBER" },
+    { "TPRO", "PRODUCEDNOTICE" },
+    { "TPUB", "LABEL" },
+    { "TRCK", "TRACKNUMBER" },
+    { "TRSN", "RADIOSTATION" },
+    { "TRSO", "RADIOSTATIONOWNER" },
+    { "TSOA", "ALBUMSORT" },
+    { "TSOP", "ARTISTSORT" },
+    { "TSOT", "TITLESORT" },
+    { "TSO2", "ALBUMARTISTSORT" }, // non-standard, used by iTunes
+    { "TSRC", "ISRC" },
+    { "TSSE", "ENCODING" },
+    // URL frames
+    { "WCOP", "COPYRIGHTURL" },
+    { "WOAF", "FILEWEBPAGE" },
+    { "WOAR", "ARTISTWEBPAGE" },
+    { "WOAS", "AUDIOSOURCEWEBPAGE" },
+    { "WORS", "RADIOSTATIONWEBPAGE" },
+    { "WPAY", "PAYMENTWEBPAGE" },
+    { "WPUB", "PUBLISHERWEBPAGE" },
+    //{ "WXXX", "URL"}, handled specially
+    // Other frames
+    { "COMM", "COMMENT" },
+    //{ "USLT", "LYRICS" }, handled specially
+    // Apple iTunes proprietary frames
+    { "PCST", "PODCAST" },
+    { "TCAT", "PODCASTCATEGORY" },
+    { "TDES", "PODCASTDESC" },
+    { "TGID", "PODCASTID" },
+    { "WFED", "PODCASTURL" },
+  };
+  const size_t frameTranslationSize = sizeof(frameTranslation) / sizeof(frameTranslation[0]);
+
+  const char *txxxFrameTranslation[][2] = {
+    { "MUSICBRAINZ ALBUM ID",         "MUSICBRAINZ_ALBUMID" },
+    { "MUSICBRAINZ ARTIST ID",        "MUSICBRAINZ_ARTISTID" },
+    { "MUSICBRAINZ ALBUM ARTIST ID",  "MUSICBRAINZ_ALBUMARTISTID" },
+    { "MUSICBRAINZ RELEASE GROUP ID", "MUSICBRAINZ_RELEASEGROUPID" },
+    { "MUSICBRAINZ WORK ID",          "MUSICBRAINZ_WORKID" },
+    { "ACOUSTID ID",                  "ACOUSTID_ID" },
+    { "ACOUSTID FINGERPRINT",         "ACOUSTID_FINGERPRINT" },
+    { "MUSICIP PUID",                 "MUSICIP_PUID" },
+  };
+  const size_t txxxFrameTranslationSize = sizeof(txxxFrameTranslation) / sizeof(txxxFrameTranslation[0]);
+
+  // list of deprecated frames and their successors
+  const char *deprecatedFrames[][2] = {
+    {"TRDA", "TDRC"}, // 2.3 -> 2.4 (http://en.wikipedia.org/wiki/ID3)
+    {"TDAT", "TDRC"}, // 2.3 -> 2.4
+    {"TYER", "TDRC"}, // 2.3 -> 2.4
+    {"TIME", "TDRC"}, // 2.3 -> 2.4
+  };
+  const size_t deprecatedFramesSize = sizeof(deprecatedFrames) / sizeof(deprecatedFrames[0]);;
+}
 
 String Frame::frameIDToKey(const ByteVector &id)
 {
index 7db2dbbf5aea08bf7b85b132e29bb84bde3095a0..e778419ad83cc4a17b3af32e30102c9dc77167b4 100644 (file)
@@ -3,6 +3,7 @@
 #include <tstring.h>
 #include <mpegfile.h>
 #include <id3v1tag.h>
+#include <id3v1genres.h>
 #include <cppunit/extensions/HelperMacros.h>
 #include "utils.h"
 
@@ -13,6 +14,7 @@ class TestID3v1 : public CppUnit::TestFixture
 {
   CPPUNIT_TEST_SUITE(TestID3v1);
   CPPUNIT_TEST(testStripWhiteSpace);
+  CPPUNIT_TEST(testGenres);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -27,7 +29,7 @@ public:
       f.ID3v1Tag(true)->setArtist("Artist     ");
       f.save();
     }
-    
+
     {
       MPEG::File f(newname.c_str());
       CPPUNIT_ASSERT(f.ID3v1Tag(false));
@@ -35,6 +37,12 @@ public:
     }
   }
 
+  void testGenres()
+  {
+    CPPUNIT_ASSERT_EQUAL(String("Darkwave"), ID3v1::genre(50));
+    CPPUNIT_ASSERT_EQUAL(100, ID3v1::genreIndex("Humour"));
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestID3v1);