bool CTagLoaderTagLib::ParseASF(ASF::Tag *asf, EmbeddedArt *art, CMusicInfoTag& tag) { if (!asf) return false; tag.SetTitle(asf->title().to8Bit(true)); const ASF::AttributeListMap& attributeListMap = asf->attributeListMap(); for (ASF::AttributeListMap::ConstIterator it = attributeListMap.begin(); it != attributeListMap.end(); ++it) { if (it->first == "Author") SetArtist(tag, GetASFStringList(it->second)); else if (it->first == "WM/AlbumArtist") SetAlbumArtist(tag, GetASFStringList(it->second)); else if (it->first == "WM/AlbumTitle") tag.SetAlbum(it->second.front().toString().to8Bit(true)); else if (it->first == "WM/TrackNumber" || it->first == "WM/Track") { if (it->second.front().type() == ASF::Attribute::DWordType) tag.SetTrackNumber(it->second.front().toUInt()); else tag.SetTrackNumber(atoi(it->second.front().toString().toCString(true))); } else if (it->first == "WM/PartOfSet") tag.SetPartOfSet(atoi(it->second.front().toString().toCString(true))); else if (it->first == "WM/Genre") SetGenre(tag, GetASFStringList(it->second)); else if (it->first == "WM/AlbumArtistSortOrder") {} // Known unsupported, supress warnings else if (it->first == "WM/ArtistSortOrder") {} // Known unsupported, supress warnings else if (it->first == "WM/Script") {} // Known unsupported, supress warnings else if (it->first == "WM/Year") tag.SetYear(atoi(it->second.front().toString().toCString(true))); else if (it->first == "MusicBrainz/Artist Id") tag.SetMusicBrainzArtistID(GetASFStringList(it->second)); else if (it->first == "MusicBrainz/Album Id") tag.SetMusicBrainzAlbumID(it->second.front().toString().to8Bit(true)); else if (it->first == "MusicBrainz/Album Artist") SetAlbumArtist(tag, GetASFStringList(it->second)); else if (it->first == "MusicBrainz/Album Artist Id") tag.SetMusicBrainzAlbumArtistID(GetASFStringList(it->second)); else if (it->first == "MusicBrainz/Track Id") tag.SetMusicBrainzTrackID(it->second.front().toString().to8Bit(true)); else if (it->first == "MusicBrainz/Album Status") {} else if (it->first == "MusicBrainz/Album Type") {} else if (it->first == "MusicIP/PUID") {} else if (it->first == "replaygain_track_gain") tag.SetReplayGainTrackGain((int)(atof(it->second.front().toString().toCString(true)) * 100 + 0.5)); else if (it->first == "replaygain_album_gain") tag.SetReplayGainAlbumGain((int)(atof(it->second.front().toString().toCString(true)) * 100 + 0.5)); else if (it->first == "replaygain_track_peak") tag.SetReplayGainTrackPeak((float)atof(it->second.front().toString().toCString(true))); else if (it->first == "replaygain_album_peak") tag.SetReplayGainAlbumPeak((float)atof(it->second.front().toString().toCString(true))); else if (it->first == "WM/Picture") { // picture ASF::Picture pic = it->second.front().toPicture(); tag.SetCoverArtInfo(pic.picture().size(), pic.mimeType().toCString()); if (art) art->set((const uint8_t *)pic.picture().data(), pic.picture().size(), pic.mimeType().toCString()); } else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) CLog::Log(LOGDEBUG, "unrecognized ASF tag name: %s", it->first.toCString(true)); } // artist may be specified in the ContentDescription block rather than using the 'Author' attribute. if (tag.GetArtist().empty()) tag.SetArtist(asf->artist().toCString(true)); tag.SetLoaded(true); return true; }
bool CTagLoaderTagLib::ParseAPETag(APE::Tag *ape, EmbeddedArt *art, CMusicInfoTag& tag) { if (!ape) return false; const APE::ItemListMap itemListMap = ape->itemListMap(); for (APE::ItemListMap::ConstIterator it = itemListMap.begin(); it != itemListMap.end(); ++it) { if (it->first == "ARTIST") SetArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "ALBUM ARTIST") SetAlbumArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "ALBUM") tag.SetAlbum(it->second.toString().to8Bit(true)); else if (it->first == "TITLE") tag.SetTitle(it->second.toString().to8Bit(true)); else if (it->first == "TRACKNUMBER") tag.SetTrackNumber(it->second.toString().toInt()); else if (it->first == "DISCNUMBER") tag.SetPartOfSet(it->second.toString().toInt()); else if (it->first == "YEAR") tag.SetYear(it->second.toString().toInt()); else if (it->first == "GENRE") SetGenre(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "COMMENT") tag.SetComment(it->second.toString().to8Bit(true)); else if (it->first == "ENCODEDBY") {} else if (it->first == "COMPILATION") tag.SetCompilation(it->second.toString().toInt() == 1); else if (it->first == "LYRICS") tag.SetLyrics(it->second.toString().to8Bit(true)); else if (it->first == "REPLAYGAIN_TRACK_GAIN") tag.SetReplayGainTrackGain((int)(atof(it->second.toString().toCString(true)) * 100 + 0.5)); else if (it->first == "REPLAYGAIN_ALBUM_GAIN") tag.SetReplayGainAlbumGain((int)(atof(it->second.toString().toCString(true)) * 100 + 0.5)); else if (it->first == "REPLAYGAIN_TRACK_PEAK") tag.SetReplayGainTrackPeak((float)atof(it->second.toString().toCString(true))); else if (it->first == "REPLAYGAIN_ALBUM_PEAK") tag.SetReplayGainAlbumPeak((float)atof(it->second.toString().toCString(true))); else if (it->first == "MUSICBRAINZ_ARTISTID") tag.SetMusicBrainzArtistID(it->second.toString().to8Bit(true)); else if (it->first == "MUSICBRAINZ_ALBUMARTISTID") tag.SetMusicBrainzAlbumArtistID(it->second.toString().to8Bit(true)); else if (it->first == "MUSICBRAINZ_ALBUMID") tag.SetMusicBrainzAlbumID(it->second.toString().to8Bit(true)); else if (it->first == "MUSICBRAINZ_TRACKID") tag.SetMusicBrainzTrackID(it->second.toString().to8Bit(true)); else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) CLog::Log(LOGDEBUG, "unrecognized APE tag: %s", it->first.toCString(true)); } return true; }
bool CTagLoaderTagLib::ParseTag(Tag *generic, EmbeddedArt *art, CMusicInfoTag& tag) { if (!generic) return false; PropertyMap properties = generic->properties(); for (PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it) { if (it->first == "ARTIST") SetArtist(tag, StringListToVectorString(it->second)); else if (it->first == "ALBUM") tag.SetAlbum(it->second.front().to8Bit(true)); else if (it->first == "TITLE") tag.SetTitle(it->second.front().to8Bit(true)); else if (it->first == "TRACKNUMBER") tag.SetTrackNumber(it->second.front().toInt()); else if (it->first == "YEAR") tag.SetYear(it->second.front().toInt()); else if (it->first == "GENRE") SetGenre(tag, StringListToVectorString(it->second)); else if (it->first == "COMMENT") tag.SetComment(it->second.front().to8Bit(true)); } return true; }
void CMusicInfoTagLoaderWMA::SetTagValueUnsigned(const CStdString& strFrameName, uint32_t value, CMusicInfoTag& tag) { if (strFrameName == "WM/TrackNumber") { if (tag.GetTrackNumber() <= 0) tag.SetTrackNumber(value); } }
bool CTagLoaderTagLib::ParseMP4Tag(MP4::Tag *mp4, EmbeddedArt *art, CMusicInfoTag& tag) { if (!mp4) return false; MP4::ItemListMap& itemListMap = mp4->itemListMap(); for (MP4::ItemListMap::ConstIterator it = itemListMap.begin(); it != itemListMap.end(); ++it) { if (it->first == "\251nam") tag.SetTitle(it->second.toStringList().front().to8Bit(true)); else if (it->first == "\251ART") SetArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "\251alb") tag.SetAlbum(it->second.toStringList().front().to8Bit(true)); else if (it->first == "aART") SetAlbumArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "\251gen") SetGenre(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "\251cmt") tag.SetComment(it->second.toStringList().front().to8Bit(true)); else if (it->first == "cpil") tag.SetCompilation(it->second.toBool()); else if (it->first == "trkn") tag.SetTrackNumber(it->second.toIntPair().first); else if (it->first == "disk") tag.SetPartOfSet(it->second.toIntPair().first); else if (it->first == "\251day") tag.SetYear(it->second.toStringList().front().toInt()); else if (it->first == "----:com.apple.iTunes:MusicBrainz Artist Id") tag.SetMusicBrainzArtistID(it->second.toStringList().front().to8Bit(true)); else if (it->first == "----:com.apple.iTunes:MusicBrainz Album Artist Id") tag.SetMusicBrainzAlbumArtistID(it->second.toStringList().front().to8Bit(true)); else if (it->first == "----:com.apple.iTunes:MusicBrainz Album Id") tag.SetMusicBrainzAlbumID(it->second.toStringList().front().to8Bit(true)); else if (it->first == "----:com.apple.iTunes:MusicBrainz Track Id") tag.SetMusicBrainzTrackID(it->second.toStringList().front().to8Bit(true)); else if (it->first == "covr") { MP4::CoverArtList coverArtList = it->second.toCoverArtList(); for (MP4::CoverArtList::ConstIterator pt = coverArtList.begin(); pt != coverArtList.end(); ++pt) { string mime; switch (pt->format()) { case MP4::CoverArt::PNG: mime = "image/png"; break; case MP4::CoverArt::JPEG: mime = "image/jpeg"; break; default: break; } if (mime.empty()) continue; tag.SetCoverArtInfo(pt->data().size(), mime); if (art) art->set((const uint8_t *)pt->data().data(), pt->data().size(), mime); break; // one is enough } } } return true; }
bool CTagLoaderTagLib::ParseTag(ID3v1::Tag *id3v1, EmbeddedArt *art, CMusicInfoTag& tag) { if (!id3v1) return false; tag.SetTitle(id3v1->title().to8Bit(true)); tag.SetArtist(id3v1->artist().to8Bit(true)); tag.SetAlbum(id3v1->album().to8Bit(true)); tag.SetComment(id3v1->comment().to8Bit(true)); tag.SetGenre(id3v1->genre().to8Bit(true)); tag.SetYear(id3v1->year()); tag.SetTrackNumber(id3v1->track()); return true; }
bool CTagLoaderTagLib::ParseXiphComment(Ogg::XiphComment *xiph, EmbeddedArt *art, CMusicInfoTag& tag) { if (!xiph) return false; const Ogg::FieldListMap& fieldListMap = xiph->fieldListMap(); for (Ogg::FieldListMap::ConstIterator it = fieldListMap.begin(); it != fieldListMap.end(); ++it) { if (it->first == "ARTIST") SetArtist(tag, StringListToVectorString(it->second)); else if (it->first == "ALBUMARTIST") SetAlbumArtist(tag, StringListToVectorString(it->second)); else if (it->first == "ALBUM ARTIST") SetAlbumArtist(tag, StringListToVectorString(it->second)); else if (it->first == "ALBUM") tag.SetAlbum(it->second.front().to8Bit(true)); else if (it->first == "TITLE") tag.SetTitle(it->second.front().to8Bit(true)); else if (it->first == "TRACKNUMBER") tag.SetTrackNumber(it->second.front().toInt()); else if (it->first == "DISCNUMBER") tag.SetPartOfSet(it->second.front().toInt()); else if (it->first == "YEAR") tag.SetYear(it->second.front().toInt()); else if (it->first == "DATE") tag.SetYear(it->second.front().toInt()); else if (it->first == "GENRE") SetGenre(tag, StringListToVectorString(it->second)); else if (it->first == "COMMENT") tag.SetComment(it->second.front().to8Bit(true)); else if (it->first == "ENCODEDBY") {} else if (it->first == "ENSEMBLE") {} else if (it->first == "COMPILATION") tag.SetCompilation(it->second.front().toInt() == 1); else if (it->first == "LYRICS") tag.SetLyrics(it->second.front().to8Bit(true)); else if (it->first == "REPLAYGAIN_TRACK_GAIN") tag.SetReplayGainTrackGain((int)(atof(it->second.front().toCString(true)) * 100 + 0.5)); else if (it->first == "REPLAYGAIN_ALBUM_GAIN") tag.SetReplayGainAlbumGain((int)(atof(it->second.front().toCString(true)) * 100 + 0.5)); else if (it->first == "REPLAYGAIN_TRACK_PEAK") tag.SetReplayGainTrackPeak((float)atof(it->second.front().toCString(true))); else if (it->first == "REPLAYGAIN_ALBUM_PEAK") tag.SetReplayGainAlbumPeak((float)atof(it->second.front().toCString(true))); else if (it->first == "MUSICBRAINZ_ARTISTID") tag.SetMusicBrainzArtistID(it->second.front().to8Bit(true)); else if (it->first == "MUSICBRAINZ_ALBUMARTISTID") tag.SetMusicBrainzAlbumArtistID(it->second.front().to8Bit(true)); else if (it->first == "MUSICBRAINZ_ALBUMID") tag.SetMusicBrainzAlbumID(it->second.front().to8Bit(true)); else if (it->first == "MUSICBRAINZ_TRACKID") tag.SetMusicBrainzTrackID(it->second.front().to8Bit(true)); else if (it->first == "RATING") { // Vorbis ratings are a mess because the standard forgot to mention anything about them. // If you want to see how emotive the issue is and the varying standards, check here: // http://forums.winamp.com/showthread.php?t=324512 // The most common standard in that thread seems to be a 0-100 scale for 1-5 stars. // So, that's what we'll support for now. int iRating = it->second.front().toInt(); if (iRating > 0 && iRating <= 100) tag.SetRating((iRating / 20) + '0'); } else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) CLog::Log(LOGDEBUG, "unrecognized XipComment name: %s", it->first.toCString(true)); } return true; }
bool CEncoderLame::Close() { // may return one more mp3 frames int iBytes = m_dll.lame_encode_flush(m_pGlobalFlags, m_buffer, sizeof(m_buffer)); if (iBytes < 0) { CLog::Log(LOGERROR, "Internal Lame error: %i", iBytes); return false; } WriteStream(m_buffer, iBytes); FlushStream(); FileClose(); // open again, but now the old way, lame only accepts FILE pointers FILE* file = fopen_utf8(m_strFile.c_str(), "rb+"); if (!file) { CLog::Log(LOGERROR, "Error: Cannot open file for writing tags: %s", m_strFile.c_str()); return false; } m_dll.lame_mp3_tags_fid(m_pGlobalFlags, file); /* add VBR tags to mp3 file */ fclose(file); m_dll.lame_close(m_pGlobalFlags); // unload the lame dll m_dll.Unload(); // Store a id3 tag in the ripped file CID3Tag id3tag; CMusicInfoTag tag; tag.SetAlbum(m_strAlbum); tag.SetAlbumArtist(m_strAlbumArtist); tag.SetArtist(m_strArtist); tag.SetGenre(m_strGenre); tag.SetTitle(m_strTitle); tag.SetTrackNumber(atoi(m_strTrack.c_str())); SYSTEMTIME time; time.wYear=atoi(m_strYear.c_str()); tag.SetReleaseDate(time); id3tag.SetMusicInfoTag(tag); id3tag.Write(m_strFile); return true; }
bool CMusicInfoTagLoaderApe::Load(const CStdString& strFileName, CMusicInfoTag& tag, EmbeddedArt *art) { try { // retrieve the APE Tag info from strFileName // and put it in tag tag.SetURL(strFileName); DVDPlayerCodec codec; if (codec.Init(strFileName, 4096)) { tag.SetDuration((int)(codec.m_TotalTime/1000)); codec.DeInit(); } CAPEv2Tag myTag; if (myTag.ReadTag((char*)strFileName.c_str())) // true to check ID3 tag as well { tag.SetTitle(myTag.GetTitle()); tag.SetAlbum(myTag.GetAlbum()); tag.SetArtist(myTag.GetArtist()); tag.SetAlbumArtist(myTag.GetAlbumArtist()); tag.SetGenre(myTag.GetGenre()); tag.SetTrackNumber(myTag.GetTrackNum()); tag.SetPartOfSet(myTag.GetDiscNum()); tag.SetComment(myTag.GetComment()); tag.SetLyrics(myTag.GetLyrics()); tag.SetMusicBrainzAlbumArtistID(myTag.GetMusicBrainzAlbumArtistID()); tag.SetMusicBrainzAlbumID(myTag.GetMusicBrainzAlbumID()); tag.SetMusicBrainzArtistID(myTag.GetMusicBrainzArtistID()); tag.SetMusicBrainzTrackID(myTag.GetMusicBrainzTrackID()); tag.SetMusicBrainzTRMID(myTag.GetMusicBrainzTRMID()); SYSTEMTIME dateTime; ZeroMemory(&dateTime, sizeof(SYSTEMTIME)); dateTime.wYear = atoi(myTag.GetYear()); tag.SetRating(myTag.GetRating()); tag.SetReleaseDate(dateTime); tag.SetLoaded(); return true; } } catch (...) { CLog::Log(LOGERROR, "Tag loader ape: exception in file %s", strFileName.c_str()); } tag.SetLoaded(false); return false; }
bool CMusicInfoTagLoaderASAP::Load(const CStdString &strFile, CMusicInfoTag &tag, EmbeddedArt *art) { tag.SetLoaded(false); if (!m_dll.Load()) return false; CStdString strFileToLoad = strFile; int song = -1; CStdString strExtension; URIUtils::GetExtension(strFile, strExtension); strExtension.MakeLower(); if (strExtension == ".asapstream") { CStdString strFileName = URIUtils::GetFileName(strFile); int iStart = strFileName.ReverseFind('-') + 1; song = atoi(strFileName.substr(iStart, strFileName.size() - iStart - 11).c_str()) - 1; CStdString strPath = strFile; URIUtils::GetDirectory(strPath, strFileToLoad); URIUtils::RemoveSlashAtEnd(strFileToLoad); } ASAP_SongInfo songInfo; if (!m_dll.asapGetInfo(strFileToLoad.c_str(), song, &songInfo)) return false; tag.SetURL(strFileToLoad); if (songInfo.name[0] != '\0') tag.SetTitle(songInfo.name); if (songInfo.author[0] != '\0') tag.SetArtist(songInfo.author); if (song >= 0) tag.SetTrackNumber(song + 1); if (songInfo.duration >= 0) tag.SetDuration(songInfo.duration / 1000); if (songInfo.year > 0) { SYSTEMTIME dateTime = { (WORD)songInfo.year, (WORD)songInfo.month, 0, (WORD)songInfo.day, 0, 0, 0, 0 }; tag.SetReleaseDate(dateTime); } tag.SetLoaded(true); return true; }
bool CMusicInfoTagLoaderApe::Load(const CStdString& strFileName, CMusicInfoTag& tag) { try { // retrieve the APE Tag info from strFileName // and put it in tag tag.SetURL(strFileName); CAPEv2Tag myTag; if (myTag.ReadTag((char*)strFileName.c_str())) // true to check ID3 tag as well { tag.SetTitle(myTag.GetTitle()); tag.SetAlbum(myTag.GetAlbum()); tag.SetArtist(myTag.GetArtist()); tag.SetAlbumArtist(myTag.GetAlbumArtist()); tag.SetGenre(myTag.GetGenre()); tag.SetTrackNumber(myTag.GetTrackNum()); tag.SetPartOfSet(myTag.GetDiscNum()); tag.SetComment(myTag.GetComment()); tag.SetLyrics(myTag.GetLyrics()); SYSTEMTIME dateTime; ZeroMemory(&dateTime, sizeof(SYSTEMTIME)); dateTime.wYear = atoi(myTag.GetYear()); tag.SetRating(myTag.GetRating()); tag.SetReleaseDate(dateTime); tag.SetLoaded(); return true; } } catch (...) { CLog::Log(LOGERROR, "Tag loader ape: exception in file %s", strFileName.c_str()); } tag.SetLoaded(false); return false; }
void CMusicInfoTagLoaderMP4::ParseTag( unsigned int metaKey, const char* pMetaData, int metaSize, CMusicInfoTag& tag, EmbeddedArt *art) { switch ( metaKey ) { case g_TitleAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; // we use utf8 internally tag.SetLoaded( true ); tag.SetTitle( dataWorkspace.get() ); break; } case g_ArtistAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetArtist( dataWorkspace.get() ); break; } case g_AlbumAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetAlbum( dataWorkspace.get() ); break; } case g_AlbumArtistAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetAlbumArtist( dataWorkspace.get() ); break; } case g_DayAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; SYSTEMTIME dateTime; dateTime.wYear = atoi( dataWorkspace.get() ); tag.SetReleaseDate( dateTime ); break; } case g_GenreAtomName: { // When a genre number is specified, we need to translate to a string for display.. // Note that AAC/iTunes genre numbers are the same as ID3 numbers, but are offset by 1. const char* pGenre = ID3_V1GENRE2DESCRIPTION( (unsigned char)pMetaData[ 1 ] - 1 ); if ( pGenre ) { tag.SetGenre( pGenre ); } break; } case g_CompilationAtomName: { if (metaSize == 1) tag.SetCompilation(*pMetaData == 1); break; } case g_CommentAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetComment( dataWorkspace.get() ); break; } case g_LyricsAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetLyrics( dataWorkspace.get() ); break; } case g_CustomGenreAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetGenre( dataWorkspace.get() ); break; } case g_TrackNumberAtomName: { tag.SetTrackNumber( (unsigned char)pMetaData[ 3 ] ); break; } case g_DiscNumberAtomName: { tag.SetPartOfSet( (unsigned char)pMetaData[ 3 ] ); break; } case g_CoverArtAtomName: { // This cover-art handling is pretty much what was in the old MP4 tag processing code.. // note that according to http://atomicparsley.sourceforge.net/mpeg-4files.html the type // of image (PNG=14 or JPG=13) is contained in pMetadata[-5] std::string mimeType; if (pMetaData[-5] == 13) mimeType = "image/jpeg"; else if (pMetaData[-5] == 14) mimeType = "image/png"; else CLog::Log(LOGDEBUG, "Unknown art mimetype %d", pMetaData[-5]); tag.SetCoverArtInfo(metaSize, mimeType); if (art) art->set((const uint8_t*)pMetaData, metaSize, mimeType); break; } default: break; } }
bool CTagLoaderTagLib::ParseTag(Ogg::XiphComment *xiph, EmbeddedArt *art, CMusicInfoTag& tag) { if (!xiph) return false; FLAC::Picture pictures[3]; ReplayGain replayGainInfo; const Ogg::FieldListMap& fieldListMap = xiph->fieldListMap(); for (Ogg::FieldListMap::ConstIterator it = fieldListMap.begin(); it != fieldListMap.end(); ++it) { if (it->first == "ARTIST") SetArtist(tag, StringListToVectorString(it->second)); else if (it->first == "ARTISTS") tag.SetMusicBrainzArtistHints(StringListToVectorString(it->second)); else if (it->first == "ALBUMARTIST" || it->first == "ALBUM ARTIST") SetAlbumArtist(tag, StringListToVectorString(it->second)); else if (it->first == "ALBUMARTISTS" || it->first == "ALBUM ARTISTS") tag.SetMusicBrainzAlbumArtistHints(StringListToVectorString(it->second)); else if (it->first == "ALBUM") tag.SetAlbum(it->second.front().to8Bit(true)); else if (it->first == "TITLE") tag.SetTitle(it->second.front().to8Bit(true)); else if (it->first == "TRACKNUMBER") tag.SetTrackNumber(it->second.front().toInt()); else if (it->first == "DISCNUMBER") tag.SetDiscNumber(it->second.front().toInt()); else if (it->first == "YEAR") tag.SetYear(it->second.front().toInt()); else if (it->first == "DATE") tag.SetYear(it->second.front().toInt()); else if (it->first == "GENRE") SetGenre(tag, StringListToVectorString(it->second)); else if (it->first == "COMMENT") tag.SetComment(it->second.front().to8Bit(true)); else if (it->first == "CUESHEET") tag.SetCueSheet(it->second.front().to8Bit(true)); else if (it->first == "ENCODEDBY") {} else if (it->first == "ENSEMBLE") {} else if (it->first == "COMPILATION") tag.SetCompilation(it->second.front().toInt() == 1); else if (it->first == "LYRICS") tag.SetLyrics(it->second.front().to8Bit(true)); else if (it->first == "REPLAYGAIN_TRACK_GAIN") replayGainInfo.ParseGain(ReplayGain::TRACK, it->second.front().toCString(true)); else if (it->first == "REPLAYGAIN_ALBUM_GAIN") replayGainInfo.ParseGain(ReplayGain::ALBUM, it->second.front().toCString(true)); else if (it->first == "REPLAYGAIN_TRACK_PEAK") replayGainInfo.ParsePeak(ReplayGain::TRACK, it->second.front().toCString(true)); else if (it->first == "REPLAYGAIN_ALBUM_PEAK") replayGainInfo.ParsePeak(ReplayGain::ALBUM, it->second.front().toCString(true)); else if (it->first == "MUSICBRAINZ_ARTISTID") tag.SetMusicBrainzArtistID(SplitMBID(StringListToVectorString(it->second))); else if (it->first == "MUSICBRAINZ_ALBUMARTISTID") tag.SetMusicBrainzAlbumArtistID(SplitMBID(StringListToVectorString(it->second))); else if (it->first == "MUSICBRAINZ_ALBUMARTIST") SetAlbumArtist(tag, StringListToVectorString(it->second)); else if (it->first == "MUSICBRAINZ_ALBUMID") tag.SetMusicBrainzAlbumID(it->second.front().to8Bit(true)); else if (it->first == "MUSICBRAINZ_TRACKID") tag.SetMusicBrainzTrackID(it->second.front().to8Bit(true)); else if (it->first == "RATING") { // Vorbis ratings are a mess because the standard forgot to mention anything about them. // If you want to see how emotive the issue is and the varying standards, check here: // http://forums.winamp.com/showthread.php?t=324512 // The most common standard in that thread seems to be a 0-100 scale for 1-5 stars. // So, that's what we'll support for now. int iRating = it->second.front().toInt(); if (iRating > 0 && iRating <= 100) tag.SetUserrating((iRating / 20) + '0'); } else if (it->first == "METADATA_BLOCK_PICTURE") { const char* b64 = it->second.front().toCString(); std::string decoded_block = Base64::Decode(b64, it->second.front().size()); ByteVector bv(decoded_block.data(), decoded_block.size()); TagLib::FLAC::Picture* pictureFrame = new TagLib::FLAC::Picture(bv); if (pictureFrame->type() == FLAC::Picture::FrontCover) pictures[0].parse(bv); else if (pictureFrame->type() == FLAC::Picture::Other) pictures[1].parse(bv); delete pictureFrame; } else if (it->first == "COVERART") { const char* b64 = it->second.front().toCString(); std::string decoded_block = Base64::Decode(b64, it->second.front().size()); ByteVector bv(decoded_block.data(), decoded_block.size()); pictures[2].setData(bv); // Assume jpeg if (pictures[2].mimeType().isEmpty()) pictures[2].setMimeType("image/jpeg"); } else if (it->first == "COVERARTMIME") { pictures[2].setMimeType(it->second.front()); } else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) CLog::Log(LOGDEBUG, "unrecognized XipComment name: %s", it->first.toCString(true)); } // Process the extracted picture frames; 0 = CoverArt, 1 = Other, 2 = COVERART/COVERARTMIME for (int i = 0; i < 3; ++i) if (pictures[i].data().size()) { std::string mime = pictures[i].mimeType().toCString(); if (mime.compare(0, 6, "image/") != 0) continue; TagLib::uint size = pictures[i].data().size(); tag.SetCoverArtInfo(size, mime); if (art) art->set((const uint8_t*)pictures[i].data().data(), size, mime); break; } if (xiph->comment() != String::null) tag.SetComment(xiph->comment().toCString(true)); tag.SetReplayGain(replayGainInfo); return true; }
bool CTagLoaderTagLib::ParseTag(APE::Tag *ape, EmbeddedArt *art, CMusicInfoTag& tag) { if (!ape) return false; ReplayGain replayGainInfo; const APE::ItemListMap itemListMap = ape->itemListMap(); for (APE::ItemListMap::ConstIterator it = itemListMap.begin(); it != itemListMap.end(); ++it) { if (it->first == "ARTIST") SetArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "ARTISTS") SetArtistHints(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "ALBUMARTIST" || it->first == "ALBUM ARTIST") SetAlbumArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "ALBUMARTISTS" || it->first == "ALBUM ARTISTS") SetAlbumArtistHints(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "ALBUM") tag.SetAlbum(it->second.toString().to8Bit(true)); else if (it->first == "TITLE") tag.SetTitle(it->second.toString().to8Bit(true)); else if (it->first == "TRACKNUMBER" || it->first == "TRACK") tag.SetTrackNumber(it->second.toString().toInt()); else if (it->first == "DISCNUMBER" || it->first == "DISC") tag.SetDiscNumber(it->second.toString().toInt()); else if (it->first == "YEAR") tag.SetYear(it->second.toString().toInt()); else if (it->first == "GENRE") SetGenre(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "MOOD") tag.SetMood(it->second.toString().to8Bit(true)); else if (it->first == "COMMENT") tag.SetComment(it->second.toString().to8Bit(true)); else if (it->first == "CUESHEET") tag.SetCueSheet(it->second.toString().to8Bit(true)); else if (it->first == "ENCODEDBY") {} else if (it->first == "COMPOSER") AddArtistRole(tag, "Composer", StringListToVectorString(it->second.toStringList())); else if (it->first == "CONDUCTOR") AddArtistRole(tag, "Conductor", StringListToVectorString(it->second.toStringList())); else if ((it->first == "BAND") || (it->first == "ENSEMBLE")) AddArtistRole(tag, "Orchestra", StringListToVectorString(it->second.toStringList())); else if (it->first == "LYRICIST") AddArtistRole(tag, "Lyricist", StringListToVectorString(it->second.toStringList())); else if (it->first == "MIXARTIST") AddArtistRole(tag, "Remixer", StringListToVectorString(it->second.toStringList())); else if (it->first == "ARRANGER") AddArtistRole(tag, "Arranger", StringListToVectorString(it->second.toStringList())); else if (it->first == "ENGINEER") AddArtistRole(tag, "Engineer", StringListToVectorString(it->second.toStringList())); else if (it->first == "PRODUCER") AddArtistRole(tag, "Producer", StringListToVectorString(it->second.toStringList())); else if (it->first == "DJMIXER") AddArtistRole(tag, "DJMixer", StringListToVectorString(it->second.toStringList())); else if (it->first == "MIXER") AddArtistRole(tag, "Mixer", StringListToVectorString(it->second.toStringList())); else if (it->first == "PERFORMER") // Picard uses PERFORMER tag as musician credits list formatted "name (instrument)" AddArtistInstrument(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "LABEL") {} // Publisher. Known unsupported, supress warnings else if (it->first == "COMPILATION") tag.SetCompilation(it->second.toString().toInt() == 1); else if (it->first == "LYRICS") tag.SetLyrics(it->second.toString().to8Bit(true)); else if (it->first == "REPLAYGAIN_TRACK_GAIN") replayGainInfo.ParseGain(ReplayGain::TRACK, it->second.toString().toCString(true)); else if (it->first == "REPLAYGAIN_ALBUM_GAIN") replayGainInfo.ParseGain(ReplayGain::ALBUM, it->second.toString().toCString(true)); else if (it->first == "REPLAYGAIN_TRACK_PEAK") replayGainInfo.ParsePeak(ReplayGain::TRACK, it->second.toString().toCString(true)); else if (it->first == "REPLAYGAIN_ALBUM_PEAK") replayGainInfo.ParsePeak(ReplayGain::ALBUM, it->second.toString().toCString(true)); else if (it->first == "MUSICBRAINZ_ARTISTID") tag.SetMusicBrainzArtistID(SplitMBID(StringListToVectorString(it->second.toStringList()))); else if (it->first == "MUSICBRAINZ_ALBUMARTISTID") tag.SetMusicBrainzAlbumArtistID(SplitMBID(StringListToVectorString(it->second.toStringList()))); else if (it->first == "MUSICBRAINZ_ALBUMARTIST") SetAlbumArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "MUSICBRAINZ_ALBUMID") tag.SetMusicBrainzAlbumID(it->second.toString().to8Bit(true)); else if (it->first == "MUSICBRAINZ_TRACKID") tag.SetMusicBrainzTrackID(it->second.toString().to8Bit(true)); else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) CLog::Log(LOGDEBUG, "unrecognized APE tag: %s", it->first.toCString(true)); } tag.SetReplayGain(replayGainInfo); return true; }
void CMusicInfoTagLoaderMP4::ParseTag( unsigned int metaKey, const char* pMetaData, int metaSize, CMusicInfoTag& tag) { switch ( metaKey ) { case g_TitleAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; // we use utf8 internally tag.SetLoaded( true ); tag.SetTitle( dataWorkspace.get() ); break; } case g_ArtistAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetArtist( dataWorkspace.get() ); break; } case g_AlbumAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetAlbum( dataWorkspace.get() ); break; } case g_AlbumArtistAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetAlbumArtist( dataWorkspace.get() ); break; } case g_DayAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; SYSTEMTIME dateTime; dateTime.wYear = atoi( dataWorkspace.get() ); tag.SetReleaseDate( dateTime ); break; } case g_GenreAtomName: { // When a genre number is specified, we need to translate to a string for display.. // Note that AAC/iTunes genre numbers are the same as ID3 numbers, but are offset by 1. const char* pGenre = ID3_V1GENRE2DESCRIPTION( (unsigned char)pMetaData[ 1 ] - 1 ); if ( pGenre ) { tag.SetGenre( pGenre ); } break; } case g_CompilationAtomName: { if (metaSize == 1) m_isCompilation = *pMetaData == 1; break; } case g_CommentAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetComment( dataWorkspace.get() ); break; } case g_LyricsAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetLyrics( dataWorkspace.get() ); break; } case g_CustomGenreAtomName: { // We need to zero-terminate the string, which needs workspace.. auto_aptr<char> dataWorkspace( new char[ metaSize + 1 ] ); memcpy( dataWorkspace.get(), pMetaData, metaSize ); dataWorkspace[ metaSize ] = '\0'; tag.SetGenre( dataWorkspace.get() ); break; } case g_TrackNumberAtomName: { tag.SetTrackNumber( pMetaData[ 3 ] ); break; } case g_DiscNumberAtomName: { tag.SetPartOfSet( pMetaData[ 3 ] ); break; } case g_CoverArtAtomName: { // This cover-art handling is pretty much what was in the old MP4 tag processing code.. // note that according to http://atomicparsley.sourceforge.net/mpeg-4files.html the type // of image (PNG=14 or JPG=13) is contained in pMetadata[-5] but we currently don't use this. m_thumbSize = metaSize; delete[] m_thumbData; m_thumbData = new BYTE[m_thumbSize]; if (m_thumbData) memcpy(m_thumbData, pMetaData, metaSize); break; } default: break; } }
bool CMusicInfoTagLoaderCDDA::Load(const std::string& strFileName, CMusicInfoTag& tag, EmbeddedArt *art) { #ifdef HAS_DVD_DRIVE try { tag.SetURL(strFileName); bool bResult = false; // Get information for the inserted disc CCdInfo* pCdInfo = g_mediaManager.GetCdInfo(); if (pCdInfo == NULL) return bResult; // Prepare cddb Xcddb cddb; cddb.setCacheDir(CProfilesManager::GetInstance().GetCDDBFolder()); int iTrack = atoi(strFileName.substr(13, strFileName.size() - 13 - 5).c_str()); // duration is always available tag.SetDuration( ( pCdInfo->GetTrackInformation(iTrack).nMins * 60 ) + pCdInfo->GetTrackInformation(iTrack).nSecs ); // Only load cached cddb info in this tag loader, the internet database query is made in CCDDADirectory if (pCdInfo->HasCDDBInfo() && cddb.isCDCached(pCdInfo)) { // get cddb information if (cddb.queryCDinfo(pCdInfo)) { // Fill the fileitems music tag with cddb information, if available std::string strTitle = cddb.getTrackTitle(iTrack); if (!strTitle.empty()) { // Tracknumber tag.SetTrackNumber(iTrack); // Title tag.SetTitle(strTitle); // Artist: Use track artist or disc artist std::string strArtist = cddb.getTrackArtist(iTrack); if (strArtist.empty()) cddb.getDiskArtist(strArtist); tag.SetArtist(strArtist); // Album std::string strAlbum; cddb.getDiskTitle( strAlbum ); tag.SetAlbum(strAlbum); // Album Artist std::string strAlbumArtist; cddb.getDiskArtist(strAlbumArtist); tag.SetAlbumArtist(strAlbumArtist); // Year SYSTEMTIME dateTime; dateTime.wYear = atoi(cddb.getYear().c_str()); tag.SetReleaseDate( dateTime ); // Genre tag.SetGenre( cddb.getGenre() ); tag.SetLoaded(true); bResult = true; } } } else { // No cddb info, maybe we have CD-Text trackinfo ti = pCdInfo->GetTrackInformation(iTrack); // Fill the fileitems music tag with CD-Text information, if available std::string strTitle = ti.cdtext[CDTEXT_TITLE]; if (!strTitle.empty()) { // Tracknumber tag.SetTrackNumber(iTrack); // Title tag.SetTitle(strTitle); // Get info for track zero, as we may have and need CD-Text Album info xbmc_cdtext_t discCDText = pCdInfo->GetDiscCDTextInformation(); // Artist: Use track artist or disc artist std::string strArtist = ti.cdtext[CDTEXT_PERFORMER]; if (strArtist.empty()) strArtist = discCDText[CDTEXT_PERFORMER]; tag.SetArtist(strArtist); // Album std::string strAlbum; strAlbum = discCDText[CDTEXT_TITLE]; tag.SetAlbum(strAlbum); // Genre: use track or disc genre std::string strGenre = ti.cdtext[CDTEXT_GENRE]; if (strGenre.empty()) strGenre = discCDText[CDTEXT_GENRE]; tag.SetGenre( strGenre ); tag.SetLoaded(true); bResult = true; } } return bResult; } catch (...) { CLog::Log(LOGERROR, "Tag loader CDDB: exception in file %s", strFileName.c_str()); } #endif tag.SetLoaded(false); return false; }
bool CTagLoaderTagLib::ParseTag(MP4::Tag *mp4, EmbeddedArt *art, CMusicInfoTag& tag) { if (!mp4) return false; ReplayGain replayGainInfo; MP4::ItemListMap& itemListMap = mp4->itemListMap(); for (MP4::ItemListMap::ConstIterator it = itemListMap.begin(); it != itemListMap.end(); ++it) { if (it->first == "\251nam") tag.SetTitle(it->second.toStringList().front().to8Bit(true)); else if (it->first == "\251ART") SetArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:ARTISTS") SetArtistHints(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "\251alb") tag.SetAlbum(it->second.toStringList().front().to8Bit(true)); else if (it->first == "aART") SetAlbumArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:ALBUMARTISTS") SetAlbumArtistHints(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "\251gen") SetGenre(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:MOOD") tag.SetMood(it->second.toStringList().front().to8Bit(true)); else if (it->first == "\251cmt") tag.SetComment(it->second.toStringList().front().to8Bit(true)); else if (it->first == "\251wrt") AddArtistRole(tag, "Composer", StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:CONDUCTOR") AddArtistRole(tag, "Conductor", StringListToVectorString(it->second.toStringList())); //No MP4 standard tag for "ensemble" else if (it->first == "----:com.apple.iTunes:LYRICIST") AddArtistRole(tag, "Lyricist", StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:REMIXER") AddArtistRole(tag, "Remixer", StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:ENGINEER") AddArtistRole(tag, "Engineer", StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:PRODUCER") AddArtistRole(tag, "Producer", StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:DJMIXER") AddArtistRole(tag, "DJMixer", StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:MIXER") AddArtistRole(tag, "Mixer", StringListToVectorString(it->second.toStringList())); //No MP4 standard tag for musician credits else if (it->first == "----:com.apple.iTunes:LABEL") {} // Publisher. Known unsupported, supress warnings else if (it->first == "cpil") tag.SetCompilation(it->second.toBool()); else if (it->first == "trkn") tag.SetTrackNumber(it->second.toIntPair().first); else if (it->first == "disk") tag.SetDiscNumber(it->second.toIntPair().first); else if (it->first == "\251day") tag.SetYear(it->second.toStringList().front().toInt()); else if (it->first == "----:com.apple.iTunes:replaygain_track_gain") replayGainInfo.ParseGain(ReplayGain::TRACK, it->second.toStringList().front().toCString()); else if (it->first == "----:com.apple.iTunes:replaygain_album_gain") replayGainInfo.ParseGain(ReplayGain::ALBUM, it->second.toStringList().front().toCString()); else if (it->first == "----:com.apple.iTunes:replaygain_track_peak") replayGainInfo.ParsePeak(ReplayGain::TRACK, it->second.toStringList().front().toCString()); else if (it->first == "----:com.apple.iTunes:replaygain_album_peak") replayGainInfo.ParsePeak(ReplayGain::ALBUM, it->second.toStringList().front().toCString()); else if (it->first == "----:com.apple.iTunes:MusicBrainz Artist Id") tag.SetMusicBrainzArtistID(SplitMBID(StringListToVectorString(it->second.toStringList()))); else if (it->first == "----:com.apple.iTunes:MusicBrainz Album Artist Id") tag.SetMusicBrainzAlbumArtistID(SplitMBID(StringListToVectorString(it->second.toStringList()))); else if (it->first == "----:com.apple.iTunes:MusicBrainz Album Artist") SetAlbumArtist(tag, StringListToVectorString(it->second.toStringList())); else if (it->first == "----:com.apple.iTunes:MusicBrainz Album Id") tag.SetMusicBrainzAlbumID(it->second.toStringList().front().to8Bit(true)); else if (it->first == "----:com.apple.iTunes:MusicBrainz Track Id") tag.SetMusicBrainzTrackID(it->second.toStringList().front().to8Bit(true)); else if (it->first == "covr") { MP4::CoverArtList coverArtList = it->second.toCoverArtList(); for (MP4::CoverArtList::ConstIterator pt = coverArtList.begin(); pt != coverArtList.end(); ++pt) { std::string mime; switch (pt->format()) { case MP4::CoverArt::PNG: mime = "image/png"; break; case MP4::CoverArt::JPEG: mime = "image/jpeg"; break; default: break; } if (mime.empty()) continue; tag.SetCoverArtInfo(pt->data().size(), mime); if (art) art->set(reinterpret_cast<const uint8_t *>(pt->data().data()), pt->data().size(), mime); break; // one is enough } } } if (mp4->comment() != String::null) tag.SetComment(mp4->comment().toCString(true)); tag.SetReplayGain(replayGainInfo); return true; }
void CMusicInfoTagLoaderWMA::SetTagValueString(const CStdString& strFrameName, const CStdString& strValue, CMusicInfoTag& tag) { if (strFrameName == "WM/AlbumTitle") { tag.SetAlbum(strValue); } else if (strFrameName == "WM/AlbumArtist") { if (tag.GetAlbumArtist().IsEmpty()) tag.SetAlbumArtist(strValue); } else if (strFrameName == "Author") { // Multiple artists are stored in multiple "Author" tags we have get them // separatly and merge them to our system if (tag.GetArtist().IsEmpty()) tag.SetArtist(strValue); else tag.SetArtist(tag.GetArtist() + g_advancedSettings.m_musicItemSeparator + strValue); } else if (strFrameName == "WM/TrackNumber") { if (tag.GetTrackNumber() <= 0) tag.SetTrackNumber(atoi(strValue.c_str())); } else if (strFrameName == "WM/PartOfSet") { tag.SetPartOfSet(atoi(strValue.c_str())); } //else if (strFrameName=="WM/Track") // Old Tracknumber, should not be used anymore else if (strFrameName == "WM/Year") { SYSTEMTIME dateTime; dateTime.wYear = atoi(strValue.c_str()); tag.SetReleaseDate(dateTime); } else if (strFrameName == "WM/Genre") { // Multiple genres are stared in multiple "WM/Genre" tags we have to get them // separatly and merge them to our system if (tag.GetGenre().IsEmpty()) tag.SetGenre(strValue); else tag.SetGenre(tag.GetGenre() + g_advancedSettings.m_musicItemSeparator + strValue); } else if (strFrameName == "WM/Lyrics") { tag.SetLyrics(strValue); } //else if (strFrameName=="WM/DRM") //{ // // File is DRM protected // pwszValue; //} //else if (strFrameName=="WM/Codec") //{ // pwszValue; //} //else if (strFrameName=="WM/BeatsPerMinute") //{ // pwszValue; //} //else if (strFrameName=="WM/Mood") //{ // pwszValue; //} //else if (strFrameName=="WM/RadioStationName") //{ // pwszValue; //} //else if (strFrameName=="WM/RadioStationOwner") //{ // pwszValue; //} }
bool CTagLoaderTagLib::ParseID3v2Tag(ID3v2::Tag *id3v2, EmbeddedArt *art, CMusicInfoTag& tag) { // tag.SetURL(strFile); if (!id3v2) return false; ID3v2::AttachedPictureFrame *pictures[3] = {}; const ID3v2::FrameListMap& frameListMap = id3v2->frameListMap(); for (ID3v2::FrameListMap::ConstIterator it = frameListMap.begin(); it != frameListMap.end(); ++it) { if (it->first == "TPE1") SetArtist(tag, GetID3v2StringList(it->second)); else if (it->first == "TALB") tag.SetAlbum(it->second.front()->toString().to8Bit(true)); else if (it->first == "TPE2") SetAlbumArtist(tag, GetID3v2StringList(it->second)); else if (it->first == "TIT2") tag.SetTitle(it->second.front()->toString().to8Bit(true)); else if (it->first == "TCON") SetGenre(tag, GetID3v2StringList(it->second)); else if (it->first == "TRCK") tag.SetTrackNumber(strtol(it->second.front()->toString().toCString(true), NULL, 10)); else if (it->first == "TPOS") tag.SetPartOfSet(strtol(it->second.front()->toString().toCString(true), NULL, 10)); else if (it->first == "TYER") tag.SetYear(strtol(it->second.front()->toString().toCString(true), NULL, 10)); else if (it->first == "TCMP") tag.SetCompilation((strtol(it->second.front()->toString().toCString(true), NULL, 10) == 0) ? false : true); else if (it->first == "TENC") {} // EncodedBy else if (it->first == "TCOP") {} // Copyright message else if (it->first == "TDRC") tag.SetYear(strtol(it->second.front()->toString().toCString(true), NULL, 10)); else if (it->first == "TDRL") tag.SetYear(strtol(it->second.front()->toString().toCString(true), NULL, 10)); else if (it->first == "TDTG") {} // Tagging time else if (it->first == "TLAN") {} // Languages else if (it->first == "USLT") // Loop through any lyrics frames. Could there be multiple frames, how to choose? for (ID3v2::FrameList::ConstIterator lt = it->second.begin(); lt != it->second.end(); ++lt) { ID3v2::UnsynchronizedLyricsFrame *lyricsFrame = dynamic_cast<ID3v2::UnsynchronizedLyricsFrame *> (*lt); if (lyricsFrame) tag.SetLyrics(lyricsFrame->text().to8Bit(true)); } else if (it->first == "COMM") // Loop through and look for the main (no description) comment for (ID3v2::FrameList::ConstIterator ct = it->second.begin(); ct != it->second.end(); ++ct) { ID3v2::CommentsFrame *commentsFrame = dynamic_cast<ID3v2::CommentsFrame *> (*ct); if (commentsFrame && commentsFrame->description().isEmpty()) tag.SetComment(commentsFrame->text().to8Bit(true)); } else if (it->first == "TXXX") // Loop through and process the UserTextIdentificationFrames for (ID3v2::FrameList::ConstIterator ut = it->second.begin(); ut != it->second.end(); ++ut) { ID3v2::UserTextIdentificationFrame *frame = dynamic_cast<ID3v2::UserTextIdentificationFrame *> (*ut); if (!frame) continue; // First field is the same as the description StringList stringList = frame->fieldList(); stringList.erase(stringList.begin()); if (frame->description() == "MusicBrainz Artist Id") tag.SetMusicBrainzArtistID(stringList.front().to8Bit(true)); else if (frame->description() == "MusicBrainz Album Id") tag.SetMusicBrainzAlbumID(stringList.front().to8Bit(true)); else if (frame->description() == "MusicBrainz Album Artist Id") tag.SetMusicBrainzAlbumArtistID(stringList.front().to8Bit(true)); else if (frame->description() == "replaygain_track_gain") tag.SetReplayGainTrackGain((int)(atof(stringList.front().toCString(true)) * 100 + 0.5)); else if (frame->description() == "replaygain_album_gain") tag.SetReplayGainAlbumGain((int)(atof(stringList.front().toCString(true)) * 100 + 0.5)); else if (frame->description() == "replaygain_track_peak") tag.SetReplayGainTrackPeak((float)atof(stringList.front().toCString(true))); else if (frame->description() == "replaygain_album_peak") tag.SetReplayGainAlbumPeak((float)atof(stringList.front().toCString(true))); else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) CLog::Log(LOGDEBUG, "unrecognized user text tag detected: TXXX:%s", frame->description().toCString(true)); } else if (it->first == "UFID") // Loop through any UFID frames and set them for (ID3v2::FrameList::ConstIterator ut = it->second.begin(); ut != it->second.end(); ++ut) { ID3v2::UniqueFileIdentifierFrame *ufid = reinterpret_cast<ID3v2::UniqueFileIdentifierFrame*> (*ut); if (ufid->owner() == "http://musicbrainz.org") { // MusicBrainz pads with a \0, but the spec requires binary, be cautious char cUfid[64]; int max_size = std::min((int)ufid->identifier().size(), 63); strncpy(cUfid, ufid->identifier().data(), max_size); cUfid[max_size] = '\0'; tag.SetMusicBrainzTrackID(cUfid); } } else if (it->first == "APIC") // Loop through all pictures and store the frame pointers for the picture types we want for (ID3v2::FrameList::ConstIterator pi = it->second.begin(); pi != it->second.end(); ++pi) { ID3v2::AttachedPictureFrame *pictureFrame = dynamic_cast<ID3v2::AttachedPictureFrame *> (*pi); if (!pictureFrame) continue; if (pictureFrame->type() == ID3v2::AttachedPictureFrame::FrontCover) pictures[0] = pictureFrame; else if (pictureFrame->type() == ID3v2::AttachedPictureFrame::Other) pictures[1] = pictureFrame; else if (pi == it->second.begin()) pictures[2] = pictureFrame; } else if (it->first == "POPM") // Loop through and process ratings for (ID3v2::FrameList::ConstIterator ct = it->second.begin(); ct != it->second.end(); ++ct) { ID3v2::PopularimeterFrame *popFrame = dynamic_cast<ID3v2::PopularimeterFrame *> (*ct); if (!popFrame) continue; // @xbmc.org ratings trump others (of course) if (popFrame->email() == "*****@*****.**") tag.SetRating(popFrame->rating() / 51 + '0'); else if (tag.GetRating() == '0') { if (popFrame->email() != "Windows Media Player 9 Series" && popFrame->email() != "no@email" && popFrame->email() != "*****@*****.**" && popFrame->email() != "*****@*****.**") CLog::Log(LOGDEBUG, "unrecognized ratings schema detected: %s", popFrame->email().toCString(true)); tag.SetRating(POPMtoXBMC(popFrame->rating())); } } else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) CLog::Log(LOGDEBUG, "unrecognized ID3 frame detected: %c%c%c%c", it->first[0], it->first[1], it->first[2], it->first[3]); } // for // Process the extracted picture frames; 0 = CoverArt, 1 = Other, 2 = First Found picture for (int i = 0; i < 3; ++i) if (pictures[i]) { string mime = pictures[i]->mimeType().to8Bit(true); TagLib::uint size = pictures[i]->picture().size(); tag.SetCoverArtInfo(size, mime); if (art) art->set((const uint8_t*)pictures[i]->picture().data(), size, mime); // Stop after we find the first picture for now. break; } return true; }
bool CMusicInfoTagLoaderSid::Load(const CStdString& strFileName, CMusicInfoTag& tag) { CStdString strFileToLoad = strFileName; int iTrack = 0; CStdString strExtension; CUtil::GetExtension(strFileName,strExtension); strExtension.MakeLower(); if (strExtension==".sidstream") { // Extract the track to play CStdString strFile=CUtil::GetFileName(strFileName); int iStart=strFile.ReverseFind("-")+1; iTrack = atoi(strFile.substr(iStart, strFile.size()-iStart-10).c_str()); // The directory we are in, is the file // that contains the bitstream to play, // so extract it CStdString strPath=strFileName; CUtil::GetDirectory(strPath, strFileToLoad); CUtil::RemoveSlashAtEnd(strFileToLoad); // we want the filename } CStdString strFileNameLower(strFileToLoad); strFileNameLower.MakeLower(); int iHVSC = strFileNameLower.find("hvsc"); // need hvsc in path name since our lookupfile is based on hvsc paths if (iHVSC < 0) { iHVSC = strFileNameLower.find("c64music"); if (iHVSC >= 0) iHVSC += 8; } else iHVSC += 4; if( iHVSC < 0 ) { tag.SetLoaded(false); return( false ); } CStdString strHVSCpath = strFileToLoad.substr(iHVSC,strFileToLoad.length()-1); strHVSCpath.Replace('\\','/'); // unix paths strHVSCpath.MakeLower(); char temp[8192]; CRegExp reg; if (!reg.RegComp("TITLE: ([^\r\n]*)\r?\n[^A]*ARTIST: ([^\r\n]*)\r?\n")) { CLog::Log(LOGINFO,"MusicInfoTagLoaderSid::Load(..): failed to compile regular expression"); tag.SetLoaded(false); return( false ); } sprintf(temp,"%s\\%s",g_settings.GetDatabaseFolder().c_str(),"stil.txt"); // changeme? std::ifstream f(temp); if( !f.good() ) { CLog::Log(LOGINFO,"MusicInfoTagLoaderSid::Load(..) unable to locate stil.txt"); tag.SetLoaded(false); return( false ); } const char* szStart = NULL; const char* szEnd = NULL; char temp2[8191]; char* temp3 = temp2; while( !f.eof() && !szEnd ) { f.read(temp,8191); CStdString strLower = temp; strLower.MakeLower(); if (!szStart) szStart= (char *)strstr(strLower.c_str(),strHVSCpath.c_str()); if (szStart) { szEnd = strstr(szStart+strHVSCpath.size(),".sid"); if (szEnd) { memcpy(temp3,temp+(szStart-strLower.c_str()),szEnd-szStart); temp3 += szEnd-szStart; } else { memcpy(temp3,temp+(szStart-strLower.c_str()),strlen(szStart)); szStart = NULL; temp3 += strlen(szStart); } } } f.close(); if (!f.eof() && szEnd) { temp2[temp3-temp2] = '\0'; temp3 = strstr(temp2,"TITLE:"); } else temp3 = NULL; if (temp3) { for (int i=0;i<iTrack-1;++i) // skip tracks { int iStart = reg.RegFind(temp3); if (!iStart) { tag.SetLoaded(false); return false; } temp3 += iStart; } if(reg.RegFind(temp3) > -1) { char* szTitle = reg.GetReplaceString("\\1"); char* szArtist = reg.GetReplaceString("\\2"); char* szMins = NULL; char* szSecs = NULL; CRegExp reg2; reg2.RegComp("(.*) \\(([0-9]*):([0-9]*)\\)"); if (reg2.RegFind(szTitle) > -1) { szMins = reg2.GetReplaceString("\\2"); szSecs = reg2.GetReplaceString("\\3"); char* szTemp = reg2.GetReplaceString("\\1"); free(szTitle); szTitle = szTemp; } tag.SetLoaded(true); tag.SetURL(strFileToLoad); tag.SetTrackNumber(iTrack); if (szMins && szSecs) tag.SetDuration(atoi(szMins)*60+atoi(szSecs)); tag.SetTitle(szTitle); tag.SetArtist(szArtist); if( szTitle ) free(szTitle); if( szArtist ) free(szArtist); if( szMins ) free(szMins); if( szSecs ) free(szSecs); } } sprintf(temp,"%s\\%s",g_settings.GetDatabaseFolder().c_str(),"sidlist.csv"); // changeme? std::ifstream f2(temp); if( !f2.good() ) { CLog::Log(LOGINFO,"MusicInfoTagLoaderSid::Load(..) unable to locate sidlist.csv"); tag.SetLoaded(false); return( false ); } while( !f2.eof() ) { f2.getline(temp,8191); CStdString strTemp(temp); strTemp.MakeLower(); unsigned int iFind = strTemp.find(strHVSCpath); if (iFind == string::npos) continue; char temp2[1024]; char temp3[1024]; strncpy(temp3,temp+iFind,strlen(strHVSCpath)); temp3[strlen(strHVSCpath)] = '\0'; sprintf(temp2,"\"%s\",\"[^\"]*\",\"[^\"]*\",\"([^\"]*)\",\"([^\"]*)\",\"([0-9]*)[^\"]*\",\"[0-9]*\",\"[0-9]*\",\"",temp3); for (int i=0;i<iTrack-1;++i) strcat(temp2,"[0-9]*:[0-9]* "); strcat(temp2,"([0-9]*):([0-9]*)"); if( !reg.RegComp(temp2) ) { CLog::Log(LOGINFO,"MusicInfoTagLoaderSid::Load(..): failed to compile regular expression"); tag.SetLoaded(false); return( false ); } if( reg.RegFind(temp) >= 0 ) { char* szTitle = reg.GetReplaceString("\\1"); char* szArtist = reg.GetReplaceString("\\2"); char* szYear = reg.GetReplaceString("\\3"); char* szMins = reg.GetReplaceString("\\4"); char* szSecs = reg.GetReplaceString("\\5"); tag.SetLoaded(true); tag.SetTrackNumber(iTrack); if (tag.GetDuration() == 0) tag.SetDuration(atoi(szMins)*60+atoi(szSecs)); if (tag.GetTitle() == "") tag.SetTitle(szTitle); if (tag.GetArtist() == "") tag.SetArtist(szArtist); SYSTEMTIME dateTime; dateTime.wYear = atoi(szYear); tag.SetReleaseDate(dateTime); if( szTitle ) free(szTitle); if( szArtist ) free(szArtist); if( szYear ) free(szYear); if( szMins ) free(szMins); if( szSecs ) free(szSecs); f2.close(); return( true ); } } f2.close(); tag.SetLoaded(false); return( false ); }
bool CTagLoaderTagLib::ParseTag(ASF::Tag *asf, EmbeddedArt *art, CMusicInfoTag& tag) { if (!asf) return false; ReplayGain replayGainInfo; tag.SetTitle(asf->title().to8Bit(true)); const ASF::AttributeListMap& attributeListMap = asf->attributeListMap(); for (ASF::AttributeListMap::ConstIterator it = attributeListMap.begin(); it != attributeListMap.end(); ++it) { if (it->first == "Author") SetArtist(tag, GetASFStringList(it->second)); else if (it->first == "WM/AlbumArtist") SetAlbumArtist(tag, GetASFStringList(it->second)); else if (it->first == "WM/AlbumTitle") tag.SetAlbum(it->second.front().toString().to8Bit(true)); else if (it->first == "WM/TrackNumber" || it->first == "WM/Track") { if (it->second.front().type() == ASF::Attribute::DWordType) tag.SetTrackNumber(it->second.front().toUInt()); else tag.SetTrackNumber(atoi(it->second.front().toString().toCString(true))); } else if (it->first == "WM/PartOfSet") tag.SetDiscNumber(atoi(it->second.front().toString().toCString(true))); else if (it->first == "WM/Genre") SetGenre(tag, GetASFStringList(it->second)); else if (it->first == "WM/Mood") tag.SetMood(it->second.front().toString().to8Bit(true)); else if (it->first == "WM/Composer") AddArtistRole(tag, "Composer", GetASFStringList(it->second)); else if (it->first == "WM/Conductor") AddArtistRole(tag, "Conductor", GetASFStringList(it->second)); //No ASF/WMA tag from Taglib for "ensemble" else if (it->first == "WM/Writer") AddArtistRole(tag, "Lyricist", GetASFStringList(it->second)); else if (it->first == "WM/ModifiedBy") AddArtistRole(tag, "Remixer", GetASFStringList(it->second)); else if (it->first == "WM/Engineer") AddArtistRole(tag, "Engineer", GetASFStringList(it->second)); else if (it->first == "WM/Producer") AddArtistRole(tag, "Producer", GetASFStringList(it->second)); else if (it->first == "WM/DJMixer") AddArtistRole(tag, "DJMixer", GetASFStringList(it->second)); else if (it->first == "WM/Mixer") AddArtistRole(tag, "mixer", GetASFStringList(it->second)); else if (it->first == "WM/Publisher") {} // Known unsupported, supress warnings else if (it->first == "WM/AlbumArtistSortOrder") {} // Known unsupported, supress warnings else if (it->first == "WM/ArtistSortOrder") {} // Known unsupported, supress warnings else if (it->first == "WM/Script") {} // Known unsupported, supress warnings else if (it->first == "WM/Year") tag.SetYear(atoi(it->second.front().toString().toCString(true))); else if (it->first == "MusicBrainz/Artist Id") tag.SetMusicBrainzArtistID(SplitMBID(GetASFStringList(it->second))); else if (it->first == "MusicBrainz/Album Id") tag.SetMusicBrainzAlbumID(it->second.front().toString().to8Bit(true)); else if (it->first == "MusicBrainz/Album Artist") SetAlbumArtist(tag, GetASFStringList(it->second)); else if (it->first == "MusicBrainz/Album Artist Id") tag.SetMusicBrainzAlbumArtistID(SplitMBID(GetASFStringList(it->second))); else if (it->first == "MusicBrainz/Track Id") tag.SetMusicBrainzTrackID(it->second.front().toString().to8Bit(true)); else if (it->first == "MusicBrainz/Album Status") {} else if (it->first == "MusicBrainz/Album Type") {} else if (it->first == "MusicIP/PUID") {} else if (it->first == "replaygain_track_gain") replayGainInfo.ParseGain(ReplayGain::TRACK, it->second.front().toString().toCString(true)); else if (it->first == "replaygain_album_gain") replayGainInfo.ParseGain(ReplayGain::ALBUM, it->second.front().toString().toCString(true)); else if (it->first == "replaygain_track_peak") replayGainInfo.ParsePeak(ReplayGain::TRACK, it->second.front().toString().toCString(true)); else if (it->first == "replaygain_album_peak") replayGainInfo.ParsePeak(ReplayGain::ALBUM, it->second.front().toString().toCString(true)); else if (it->first == "WM/Picture") { // picture ASF::Picture pic = it->second.front().toPicture(); tag.SetCoverArtInfo(pic.picture().size(), pic.mimeType().toCString()); if (art) art->set(reinterpret_cast<const uint8_t *>(pic.picture().data()), pic.picture().size(), pic.mimeType().toCString()); } else if (g_advancedSettings.m_logLevel == LOG_LEVEL_MAX) CLog::Log(LOGDEBUG, "unrecognized ASF tag name: %s", it->first.toCString(true)); } // artist may be specified in the ContentDescription block rather than using the 'Author' attribute. if (tag.GetArtist().empty()) tag.SetArtist(asf->artist().toCString(true)); if (asf->comment() != String::null) tag.SetComment(asf->comment().toCString(true)); tag.SetReplayGain(replayGainInfo); tag.SetLoaded(true); return true; }