void CScrobbler::AddSong(const MUSIC_INFO::CMusicInfoTag &tag, bool lastfmradio) { ClearSubmissionState(); if (!CanScrobble() || !tag.Loaded()) return; if (tag.GetArtist().empty() || tag.GetTitle().IsEmpty()) return; // our tags are stored as UTF-8, so no conversion needed m_CurrentTrack.length = tag.GetDuration(); m_CurrentTrack.strArtist = StringUtils::Join(tag.GetArtist(), g_advancedSettings.m_musicItemSeparator); m_CurrentTrack.strAlbum = tag.GetAlbum(); m_CurrentTrack.strTitle = tag.GetTitle(); m_CurrentTrack.strMusicBrainzID = tag.GetMusicBrainzTrackID(); if (lastfmradio) // TODO Set source more appropriately m_CurrentTrack.strSource = "L" + tag.GetComment(); else m_CurrentTrack.strSource = "P"; m_CurrentTrack.strRating = ""; m_CurrentTrack.strLength.Format("%d", m_CurrentTrack.length); m_CurrentTrack.strStartTime.Format("%d", time(NULL)); m_CurrentTrack.strTrackNum.Format("%d",tag.GetTrackNumber()); CURL::Encode(m_CurrentTrack.strArtist); CURL::Encode(m_CurrentTrack.strTitle); CURL::Encode(m_CurrentTrack.strAlbum); CURL::Encode(m_CurrentTrack.strMusicBrainzID); m_bNotified = false; m_bSubmitted = !((lastfmradio && g_guiSettings.GetBool("scrobbler.lastfmsubmitradio")) || (!lastfmradio && g_guiSettings.GetBool("scrobbler.lastfmsubmit") && (m_CurrentTrack.length > SCROBBLER_MIN_DURATION || !m_CurrentTrack.strMusicBrainzID.IsEmpty()))); }
void CAirTunesServer::SetMetadataFromBuffer(const char *buffer, unsigned int size) { MUSIC_INFO::CMusicInfoTag tag; std::map<std::string, std::string> metadata = decodeDMAP(buffer, size); if(metadata["asal"].length()) tag.SetAlbum(metadata["asal"]);//album if(metadata["minm"].length()) tag.SetTitle(metadata["minm"]);//title if(metadata["asar"].length()) tag.SetArtist(metadata["asar"]);//artist CApplicationMessenger::Get().SetCurrentSongTag(tag); }
void CAirTunesServer::RefreshMetadata() { CSingleLock lock(m_metadataLock); MUSIC_INFO::CMusicInfoTag tag; if (m_metadata[0].length()) tag.SetAlbum(m_metadata[0]);//album if (m_metadata[1].length()) tag.SetTitle(m_metadata[1]);//title if (m_metadata[2].length()) tag.SetArtist(m_metadata[2]);//artist CApplicationMessenger::Get().SetCurrentSongTag(tag); }
void CAirTunesServer::RefreshMetadata() { CSingleLock lock(m_metadataLock); MUSIC_INFO::CMusicInfoTag tag; if (g_infoManager.GetCurrentSongTag()) tag = *g_infoManager.GetCurrentSongTag(); if (m_metadata[0].length()) tag.SetAlbum(m_metadata[0]);//album if (m_metadata[1].length()) tag.SetTitle(m_metadata[1]);//title if (m_metadata[2].length()) tag.SetArtist(m_metadata[2]);//artist CApplicationMessenger::GetInstance().PostMsg(TMSG_UPDATE_CURRENT_ITEM, 1, -1, static_cast<void*>(new CFileItem(tag))); }
bool CAudioDecoder::Load(const std::string& fileName, MUSIC_INFO::CMusicInfoTag& tag, MUSIC_INFO::EmbeddedArt* art) { if (!Initialized()) return false; char title[256]; char artist[256]; int length; if (m_pStruct->ReadTag(fileName.c_str(), title, artist, &length)) { tag.SetTitle(title); tag.SetArtist(artist); tag.SetDuration(length); return true; } return false; }
CStdString CCDDARipper::GetAlbumDirName(const MUSIC_INFO::CMusicInfoTag& infoTag) { CStdString strAlbumDir; // use audiocds.trackpathformat setting to format // directory name where CD tracks will be stored, // use only format part ending at the last '/' strAlbumDir = CSettings::Get().GetString("audiocds.trackpathformat"); int pos = max(strAlbumDir.ReverseFind('/'), strAlbumDir.ReverseFind('\\')); if (pos < 0) return ""; // no directory strAlbumDir = strAlbumDir.Left(pos); // replace %A with album artist name if (strAlbumDir.Find("%A") != -1) { CStdString strAlbumArtist = StringUtils::Join(infoTag.GetAlbumArtist(), g_advancedSettings.m_musicItemSeparator); if (strAlbumArtist.IsEmpty()) strAlbumArtist = StringUtils::Join(infoTag.GetArtist(), g_advancedSettings.m_musicItemSeparator); if (strAlbumArtist.IsEmpty()) strAlbumArtist = "Unknown Artist"; else strAlbumArtist.Replace('/', '_'); strAlbumDir.Replace("%A", strAlbumArtist); } // replace %B with album title if (strAlbumDir.Find("%B") != -1) { CStdString strAlbum = infoTag.GetAlbum(); if (strAlbum.IsEmpty()) strAlbum.Format("Unknown Album %s", CDateTime::GetCurrentDateTime().GetAsLocalizedDateTime().c_str()); else strAlbum.Replace('/', '_'); strAlbumDir.Replace("%B", strAlbum); } // replace %G with genre if (strAlbumDir.Find("%G") != -1) { CStdString strGenre = StringUtils::Join(infoTag.GetGenre(), g_advancedSettings.m_musicItemSeparator); if (strGenre.IsEmpty()) strGenre = "Unknown Genre"; else strGenre.Replace('/', '_'); strAlbumDir.Replace("%G", strGenre); } // replace %Y with year if (strAlbumDir.Find("%Y") != -1) { CStdString strYear = infoTag.GetYearString(); if (strYear.IsEmpty()) strYear = "Unknown Year"; else strYear.Replace('/', '_'); strAlbumDir.Replace("%Y", strYear); } return strAlbumDir; }
bool CTagLoaderTagLib::ParseTag(ID3v2::Tag *id3v2, MUSIC_INFO::EmbeddedArt *art, MUSIC_INFO::CMusicInfoTag& tag) { if (!id3v2) return false; ReplayGain replayGainInfo; ID3v2::AttachedPictureFrame *pictures[3] = {}; const ID3v2::FrameListMap& frameListMap = id3v2->frameListMap(); for (ID3v2::FrameListMap::ConstIterator it = frameListMap.begin(); it != frameListMap.end(); ++it) { // It is possible that the taglist is empty. In that case no useable values can be extracted. // and we should skip the tag. if (it->second.isEmpty()) continue; 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.SetDiscNumber(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 == "TMOO") tag.SetMood(it->second.front()->toString().to8Bit(true)); 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(); if (stringList.size() == 1) continue; stringList.erase(stringList.begin()); String desc = frame->description().upper(); if (desc == "MUSICBRAINZ ARTIST ID") tag.SetMusicBrainzArtistID(SplitMBID(StringListToVectorString(stringList))); else if (desc == "MUSICBRAINZ ALBUM ID") tag.SetMusicBrainzAlbumID(stringList.front().to8Bit(true)); else if (desc == "MUSICBRAINZ ALBUM ARTIST ID") tag.SetMusicBrainzAlbumArtistID(SplitMBID(StringListToVectorString(stringList))); else if (desc == "MUSICBRAINZ ALBUM ARTIST") SetAlbumArtist(tag, StringListToVectorString(stringList)); else if (desc == "REPLAYGAIN_TRACK_GAIN") replayGainInfo.ParseGain(ReplayGain::TRACK, stringList.front().toCString(true)); else if (desc == "REPLAYGAIN_ALBUM_GAIN") replayGainInfo.ParseGain(ReplayGain::ALBUM, stringList.front().toCString(true)); else if (desc == "REPLAYGAIN_TRACK_PEAK") replayGainInfo.ParsePeak(ReplayGain::TRACK, stringList.front().toCString(true)); else if (desc == "REPLAYGAIN_ALBUM_PEAK") replayGainInfo.ParsePeak(ReplayGain::ALBUM, stringList.front().toCString(true)); else if (desc == "ALBUMARTIST" || desc == "ALBUM ARTIST") SetAlbumArtist(tag, StringListToVectorString(stringList)); else if (desc == "ARTISTS") { if (id3v2->header()->majorVersion() < 4) tag.SetMusicBrainzArtistHints(StringListToVectorString(TagLib::StringList::split(stringList.front(), TagLib::String("/")))); else tag.SetMusicBrainzArtistHints(StringListToVectorString(stringList)); } else if (desc == "ALBUMARTISTS" || desc == "ALBUM ARTISTS") { if (id3v2->header()->majorVersion() < 4) tag.SetMusicBrainzAlbumArtistHints(StringListToVectorString(TagLib::StringList::split(stringList.front(), TagLib::String("/")))); else tag.SetMusicBrainzAlbumArtistHints(StringListToVectorString(stringList)); } else if (desc == "MOOD") tag.SetMood(stringList.front().to8Bit(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.SetUserrating(popFrame->rating() / 51 + '0'); else if (tag.GetUserrating() == '0') { if (popFrame->email() != "Windows Media Player 9 Series" && popFrame->email() != "Banshee" && popFrame->email() != "no@email" && popFrame->email() != "*****@*****.**" && popFrame->email() != "*****@*****.**") CLog::Log(LOGDEBUG, "unrecognized ratings schema detected: %s", popFrame->email().toCString(true)); tag.SetUserrating(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]) { std::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; } tag.SetReplayGain(replayGainInfo); return true; }
std::string CCDDARipper::GetAlbumDirName(const MUSIC_INFO::CMusicInfoTag& infoTag) { std::string strAlbumDir; // use audiocds.trackpathformat setting to format // directory name where CD tracks will be stored, // use only format part ending at the last '/' strAlbumDir = CSettings::GetInstance().GetString(CSettings::SETTING_AUDIOCDS_TRACKPATHFORMAT); size_t pos = strAlbumDir.find_last_of("/\\"); if (pos == std::string::npos) return ""; // no directory strAlbumDir = strAlbumDir.substr(0, pos); // replace %A with album artist name if (strAlbumDir.find("%A") != std::string::npos) { std::string strAlbumArtist = StringUtils::Join(infoTag.GetAlbumArtist(), g_advancedSettings.m_musicItemSeparator); if (strAlbumArtist.empty()) strAlbumArtist = StringUtils::Join(infoTag.GetArtist(), g_advancedSettings.m_musicItemSeparator); if (strAlbumArtist.empty()) strAlbumArtist = "Unknown Artist"; else StringUtils::Replace(strAlbumArtist, '/', '_'); StringUtils::Replace(strAlbumDir, "%A", strAlbumArtist); } // replace %B with album title if (strAlbumDir.find("%B") != std::string::npos) { std::string strAlbum = infoTag.GetAlbum(); if (strAlbum.empty()) strAlbum = StringUtils::Format("Unknown Album %s", CDateTime::GetCurrentDateTime().GetAsLocalizedDateTime().c_str()); else StringUtils::Replace(strAlbum, '/', '_'); StringUtils::Replace(strAlbumDir, "%B", strAlbum); } // replace %G with genre if (strAlbumDir.find("%G") != std::string::npos) { std::string strGenre = StringUtils::Join(infoTag.GetGenre(), g_advancedSettings.m_musicItemSeparator); if (strGenre.empty()) strGenre = "Unknown Genre"; else StringUtils::Replace(strGenre, '/', '_'); StringUtils::Replace(strAlbumDir, "%G", strGenre); } // replace %Y with year if (strAlbumDir.find("%Y") != std::string::npos) { std::string strYear = infoTag.GetYearString(); if (strYear.empty()) strYear = "Unknown Year"; else StringUtils::Replace(strYear, '/', '_'); StringUtils::Replace(strAlbumDir, "%Y", strYear); } return strAlbumDir; }