bool CMusicInfoTagLoaderDatabase::Load(const CStdString& strFileName, CMusicInfoTag& tag, EmbeddedArt *art) { tag.SetLoaded(false); CMusicDatabase database; database.Open(); XFILE::MUSICDATABASEDIRECTORY::CQueryParams param; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(strFileName,param); CSong song; if (database.GetSong(param.GetSongId(),song)) tag.SetSong(song); database.Close(); return tag.Loaded(); }
bool CMusicInfoLoader::LoadAdditionalTagInfo(CFileItem* pItem) { if (!pItem || pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream()) return false; if (pItem->GetProperty("hasfullmusictag") == "true") return false; // already have the information std::string path(pItem->GetPath()); if (pItem->IsMusicDb()) { // set the artist / album properties XFILE::MUSICDATABASEDIRECTORY::CQueryParams param; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(pItem->GetPath(),param); CArtist artist; CMusicDatabase database; database.Open(); if (database.GetArtist(param.GetArtistId(), artist, false)) CMusicDatabase::SetPropertiesFromArtist(*pItem,artist); CAlbum album; if (database.GetAlbum(param.GetAlbumId(), album, false)) CMusicDatabase::SetPropertiesFromAlbum(*pItem,album); path = pItem->GetMusicInfoTag()->GetURL(); } CLog::Log(LOGDEBUG, "Loading additional tag info for file %s", path.c_str()); // we load up the actual tag for this file in order to // fetch the lyrics and add it to the current music info tag CFileItem tempItem(path, false); std::unique_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(tempItem)); if (NULL != pLoader.get()) { CMusicInfoTag tag; pLoader->Load(path, tag); pItem->GetMusicInfoTag()->SetLyrics(tag.GetLyrics()); pItem->SetProperty("hasfullmusictag", "true"); return true; } return false; }
bool CMusicInfoLoader::LoadItemLookup(CFileItem* pItem) { if (m_pProgressCallback && !pItem->m_bIsFolder) m_pProgressCallback->SetProgressAdvance(); if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream()) return false; if (!pItem->HasMusicInfoTag() || !pItem->GetMusicInfoTag()->Loaded()) { // first check the cached item CFileItemPtr mapItem = (*m_mapFileItems)[pItem->GetPath()]; if (mapItem && mapItem->m_dateTime==pItem->m_dateTime && mapItem->HasMusicInfoTag() && mapItem->GetMusicInfoTag()->Loaded()) { // Query map if we previously cached the file on HD *pItem->GetMusicInfoTag() = *mapItem->GetMusicInfoTag(); if (mapItem->HasArt("thumb")) pItem->SetArt("thumb", mapItem->GetArt("thumb")); } else { std::string strPath = URIUtils::GetDirectory(pItem->GetPath()); URIUtils::AddSlashAtEnd(strPath); if (strPath!=m_strPrevPath) { // The item is from another directory as the last one, // query the database for the new directory... m_musicDatabase.GetSongsByPath(strPath, m_songsMap); m_databaseHits++; } MAPSONGS::iterator it = m_songsMap.find(pItem->GetPath()); if (it != m_songsMap.end()) { // Have we loaded this item from database before pItem->GetMusicInfoTag()->SetSong(it->second); pItem->GetMusicInfoTag()->SetCueSheet(m_musicDatabase.LoadCuesheet(it->second.strFileName)); if (!it->second.strThumb.empty()) pItem->SetArt("thumb", it->second.strThumb); } else if (pItem->IsMusicDb()) { // a music db item that doesn't have tag loaded - grab details from the database XFILE::MUSICDATABASEDIRECTORY::CQueryParams param; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(pItem->GetPath(),param); CSong song; if (m_musicDatabase.GetSong(param.GetSongId(), song)) { pItem->GetMusicInfoTag()->SetSong(song); if (!song.strThumb.empty()) pItem->SetArt("thumb", song.strThumb); } } else if (CServiceBroker::GetSettings().GetBool(CSettings::SETTING_MUSICFILES_USETAGS) || pItem->IsCDDA()) { // Nothing found, load tag from file, // always try to load cddb info // get correct tag parser std::unique_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(*pItem)); if (NULL != pLoader.get()) // get tag pLoader->Load(pItem->GetPath(), *pItem->GetMusicInfoTag()); m_tagReads++; } m_strPrevPath = strPath; } } return true; }
bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdString& strArtist, const CStdString& strAlbum, bool& bCanceled, CMusicAlbumInfo& albumInfo, CGUIDialogProgress* pDialog) { CAlbum album; VECSONGS songs; XFILE::MUSICDATABASEDIRECTORY::CQueryParams params; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(strPath, params); bCanceled = false; m_musicDatabase.Open(); if (m_musicDatabase.HasAlbumInfo(params.GetAlbumId()) && m_musicDatabase.GetAlbumInfo(params.GetAlbumId(),album,&songs)) return true; // find album info ADDON::ScraperPtr info; if (!m_musicDatabase.GetScraperForPath(strPath, info, ADDON::ADDON_SCRAPER_ALBUMS) || !info) { m_musicDatabase.Close(); return false; } if (m_handle) { m_handle->SetTitle(StringUtils::Format(g_localizeStrings.Get(20321), info->Name().c_str())); m_handle->SetText(strArtist+" - "+strAlbum); } // clear our scraper cache info->ClearCache(); CMusicInfoScraper scraper(info); // handle nfo files CStdString strAlbumPath, strNfo; m_musicDatabase.GetAlbumPath(params.GetAlbumId(),strAlbumPath); URIUtils::AddFileToFolder(strAlbumPath,"album.nfo",strNfo); CNfoFile::NFOResult result=CNfoFile::NO_NFO; CNfoFile nfoReader; if (XFILE::CFile::Exists(strNfo)) { CLog::Log(LOGDEBUG,"Found matching nfo file: %s", strNfo.c_str()); result = nfoReader.Create(strNfo, info, -1, strPath); if (result == CNfoFile::FULL_NFO) { CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__); CAlbum album; nfoReader.GetDetails(album); m_musicDatabase.SetAlbumInfo(params.GetAlbumId(), album, album.songs); GetAlbumArtwork(params.GetAlbumId(), album); m_musicDatabase.Close(); return true; } else if (result == CNfoFile::URL_NFO || result == CNfoFile::COMBINED_NFO) { CScraperUrl scrUrl(nfoReader.ScraperUrl()); CMusicAlbumInfo album("nfo",scrUrl); info = nfoReader.GetScraperInfo(); CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",info->Name().c_str()); CLog::Log(LOGDEBUG,"-- nfo url: %s", scrUrl.m_url[0].m_url.c_str()); scraper.SetScraperInfo(info); scraper.GetAlbums().push_back(album); } else CLog::Log(LOGERROR,"Unable to find an url in nfo file: %s", strNfo.c_str()); } if (!scraper.CheckValidOrFallback(g_guiSettings.GetString("musiclibrary.albumsscraper"))) { // the current scraper is invalid, as is the default - bail CLog::Log(LOGERROR, "%s - current and default scrapers are invalid. Pick another one", __FUNCTION__); return false; } if (!scraper.GetAlbumCount()) { scraper.FindAlbumInfo(strAlbum, strArtist); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); bCanceled = true; } Sleep(1); } } CGUIDialogSelect *pDlg=NULL; int iSelectedAlbum=0; if (result == CNfoFile::NO_NFO) { iSelectedAlbum = -1; // set negative so that we can detect a failure if (scraper.Succeeded() && scraper.GetAlbumCount() >= 1) { int bestMatch = -1; double bestRelevance = 0; double minRelevance = THRESHOLD; if (scraper.GetAlbumCount() > 1) // score the matches { //show dialog with all albums found if (pDialog) { pDlg = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); pDlg->SetHeading(g_localizeStrings.Get(181).c_str()); pDlg->Reset(); pDlg->EnableButton(true, 413); // manual } for (int i = 0; i < scraper.GetAlbumCount(); ++i) { CMusicAlbumInfo& info = scraper.GetAlbum(i); double relevance = info.GetRelevance(); if (relevance < 0) relevance = CUtil::AlbumRelevance(info.GetAlbum().strAlbum, strAlbum, StringUtils::Join(info.GetAlbum().artist, g_advancedSettings.m_musicItemSeparator), strArtist); // if we're doing auto-selection (ie querying all albums at once, then allow 95->100% for perfect matches) // otherwise, perfect matches only if (relevance >= max(minRelevance, bestRelevance)) { // we auto-select the best of these bestRelevance = relevance; bestMatch = i; } if (pDialog) { // set the label to [relevance] album - artist CStdString strTemp; strTemp.Format("[%0.2f] %s", relevance, info.GetTitle2()); CFileItem item(strTemp); item.m_idepth = i; // use this to hold the index of the album in the scraper pDlg->Add(&item); } if (relevance > .99f) // we're so close, no reason to search further break; } } else { CMusicAlbumInfo& info = scraper.GetAlbum(0); double relevance = info.GetRelevance(); if (relevance < 0) relevance = CUtil::AlbumRelevance(info.GetAlbum().strAlbum, strAlbum, StringUtils::Join(info.GetAlbum().artist, g_advancedSettings.m_musicItemSeparator), strArtist); if (relevance < THRESHOLD) { m_musicDatabase.Close(); return false; } bestRelevance = relevance; bestMatch = 0; } iSelectedAlbum = bestMatch; if (pDialog && bestRelevance < THRESHOLD) { pDlg->Sort(false); pDlg->DoModal(); // and wait till user selects one if (pDlg->GetSelectedLabel() < 0) { // none chosen if (!pDlg->IsButtonPressed()) { bCanceled = true; return false; } // manual button pressed CStdString strNewAlbum = strAlbum; if (!CGUIKeyboardFactory::ShowAndGetInput(strNewAlbum, g_localizeStrings.Get(16011), false)) return false; if (strNewAlbum == "") return false; CStdString strNewArtist = strArtist; if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; pDialog->SetLine(0, strNewAlbum); pDialog->SetLine(1, strNewArtist); pDialog->Progress(); m_musicDatabase.Close(); return DownloadAlbumInfo(strPath,strNewArtist,strNewAlbum,bCanceled,albumInfo,pDialog); } iSelectedAlbum = pDlg->GetSelectedItem()->m_idepth; } } if (iSelectedAlbum < 0) { m_musicDatabase.Close(); return false; } } scraper.LoadAlbumInfo(iSelectedAlbum); while (!scraper.Completed()) { if (m_bStop) { bCanceled = true; scraper.Cancel(); } Sleep(1); } if (scraper.Succeeded()) { albumInfo = scraper.GetAlbum(iSelectedAlbum); album = scraper.GetAlbum(iSelectedAlbum).GetAlbum(); if (result == CNfoFile::COMBINED_NFO) nfoReader.GetDetails(album,NULL,true); m_musicDatabase.SetAlbumInfo(params.GetAlbumId(), album, scraper.GetAlbum(iSelectedAlbum).GetSongs(),false); } else { m_musicDatabase.Close(); return false; } // check thumb stuff GetAlbumArtwork(params.GetAlbumId(), album); m_musicDatabase.Close(); return true; }
bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStdString& strArtist, bool& bCanceled, CGUIDialogProgress* pDialog) { XFILE::MUSICDATABASEDIRECTORY::CQueryParams params; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(strPath, params); bCanceled = false; CArtist artist; m_musicDatabase.Open(); if (m_musicDatabase.GetArtistInfo(params.GetArtistId(),artist)) // already got the info return true; // find artist info ADDON::ScraperPtr info; if (!m_musicDatabase.GetScraperForPath(strPath, info, ADDON::ADDON_SCRAPER_ARTISTS) || !info) { m_musicDatabase.Close(); return false; } if (m_handle) { m_handle->SetTitle(StringUtils::Format(g_localizeStrings.Get(20320), info->Name().c_str())); m_handle->SetText(strArtist); } // clear our scraper cache info->ClearCache(); CMusicInfoScraper scraper(info); // handle nfo files CStdString strArtistPath, strNfo; m_musicDatabase.GetArtistPath(params.GetArtistId(),strArtistPath); URIUtils::AddFileToFolder(strArtistPath,"artist.nfo",strNfo); CNfoFile::NFOResult result=CNfoFile::NO_NFO; CNfoFile nfoReader; if (XFILE::CFile::Exists(strNfo)) { CLog::Log(LOGDEBUG,"Found matching nfo file: %s", strNfo.c_str()); result = nfoReader.Create(strNfo, info); if (result == CNfoFile::FULL_NFO) { CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__); CArtist artist; nfoReader.GetDetails(artist); m_musicDatabase.SetArtistInfo(params.GetArtistId(), artist); map<string, string> artwork = GetArtistArtwork(params.GetArtistId(), &artist); m_musicDatabase.SetArtForItem(params.GetArtistId(), "artist", artwork); m_musicDatabase.Close(); return true; } else if (result == CNfoFile::URL_NFO || result == CNfoFile::COMBINED_NFO) { CScraperUrl scrUrl(nfoReader.ScraperUrl()); CMusicArtistInfo artist("nfo",scrUrl); info = nfoReader.GetScraperInfo(); CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",info->Name().c_str()); CLog::Log(LOGDEBUG,"-- nfo url: %s", scrUrl.m_url[0].m_url.c_str()); scraper.SetScraperInfo(info); scraper.GetArtists().push_back(artist); } else CLog::Log(LOGERROR,"Unable to find an url in nfo file: %s", strNfo.c_str()); } if (!scraper.GetArtistCount()) { scraper.FindArtistInfo(strArtist); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); bCanceled = true; } Sleep(1); } } int iSelectedArtist = 0; if (result == CNfoFile::NO_NFO) { if (scraper.Succeeded() && scraper.GetArtistCount() >= 1) { // now load the first match if (pDialog && scraper.GetArtistCount() > 1) { // if we found more then 1 album, let user choose one CGUIDialogSelect *pDlg = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); if (pDlg) { pDlg->SetHeading(g_localizeStrings.Get(21890)); pDlg->Reset(); pDlg->EnableButton(true, 413); // manual for (int i = 0; i < scraper.GetArtistCount(); ++i) { // set the label to artist CFileItem item(scraper.GetArtist(i).GetArtist()); CStdString strTemp=scraper.GetArtist(i).GetArtist().strArtist; if (!scraper.GetArtist(i).GetArtist().strBorn.IsEmpty()) strTemp += " ("+scraper.GetArtist(i).GetArtist().strBorn+")"; if (!scraper.GetArtist(i).GetArtist().genre.empty()) { CStdString genres = StringUtils::Join(scraper.GetArtist(i).GetArtist().genre, g_advancedSettings.m_musicItemSeparator); if (!genres.empty()) strTemp.Format("[%s] %s", genres.c_str(), strTemp.c_str()); } item.SetLabel(strTemp); item.m_idepth = i; // use this to hold the index of the album in the scraper pDlg->Add(&item); } pDlg->DoModal(); // and wait till user selects one if (pDlg->GetSelectedLabel() < 0) { // none chosen if (!pDlg->IsButtonPressed()) { bCanceled = true; return false; } // manual button pressed CStdString strNewArtist = strArtist; if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, g_localizeStrings.Get(16025), false)) return false; if (pDialog) { pDialog->SetLine(0, strNewArtist); pDialog->Progress(); } m_musicDatabase.Close(); return DownloadArtistInfo(strPath,strNewArtist,bCanceled,pDialog); } iSelectedArtist = pDlg->GetSelectedItem()->m_idepth; } } } else { m_musicDatabase.Close(); return false; } } scraper.LoadArtistInfo(iSelectedArtist, strArtist); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); bCanceled = true; } Sleep(1); } if (scraper.Succeeded()) { artist = scraper.GetArtist(iSelectedArtist).GetArtist(); if (result == CNfoFile::COMBINED_NFO) nfoReader.GetDetails(artist,NULL,true); m_musicDatabase.SetArtistInfo(params.GetArtistId(), artist); } // check thumb stuff map<string, string> artwork = GetArtistArtwork(params.GetArtistId(), &artist); m_musicDatabase.SetArtForItem(params.GetArtistId(), "artist", artwork); m_musicDatabase.Close(); return true; }
bool CMusicInfoLoader::LoadItem(CFileItem* pItem) { if (m_pProgressCallback && !pItem->m_bIsFolder) m_pProgressCallback->SetProgressAdvance(); if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream()) return false; if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->Loaded()) return true; // first check the cached item CFileItemPtr mapItem = (*m_mapFileItems)[pItem->GetPath()]; if (mapItem && mapItem->m_dateTime==pItem->m_dateTime && mapItem->HasMusicInfoTag() && mapItem->GetMusicInfoTag()->Loaded()) { // Query map if we previously cached the file on HD *pItem->GetMusicInfoTag() = *mapItem->GetMusicInfoTag(); pItem->SetArt("thumb", mapItem->GetArt("thumb")); return true; } CStdString strPath; URIUtils::GetDirectory(pItem->GetPath(), strPath); URIUtils::AddSlashAtEnd(strPath); if (strPath!=m_strPrevPath) { // The item is from another directory as the last one, // query the database for the new directory... m_musicDatabase.GetSongsByPath(strPath, m_songsMap); m_databaseHits++; } CSong *song=NULL; if ((song=m_songsMap.Find(pItem->GetPath()))!=NULL) { // Have we loaded this item from database before pItem->GetMusicInfoTag()->SetSong(*song); pItem->SetArt("thumb", song->strThumb); } else if (pItem->IsMusicDb()) { // a music db item that doesn't have tag loaded - grab details from the database XFILE::MUSICDATABASEDIRECTORY::CQueryParams param; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(pItem->GetPath(),param); CSong song; if (m_musicDatabase.GetSongById(param.GetSongId(), song)) { pItem->GetMusicInfoTag()->SetSong(song); pItem->SetArt("thumb", song.strThumb); } } else if (g_guiSettings.GetBool("musicfiles.usetags") || pItem->IsCDDA()) { // Nothing found, load tag from file, // always try to load cddb info // get correct tag parser auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(pItem->GetPath())); if (NULL != pLoader.get()) // get tag pLoader->Load(pItem->GetPath(), *pItem->GetMusicInfoTag()); m_tagReads++; } m_strPrevPath = strPath; return true; }
bool CMusicInfoLoader::LoadItemLookup(CFileItem* pItem) { if (m_pProgressCallback && !pItem->m_bIsFolder) m_pProgressCallback->SetProgressAdvance(); if ((pItem->m_bIsFolder && !pItem->IsAudio()) || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream()) return false; if (!pItem->HasMusicInfoTag() || !pItem->GetMusicInfoTag()->Loaded()) { // first check the cached item CFileItemPtr mapItem = (*m_mapFileItems)[pItem->GetPath()]; if (mapItem && mapItem->m_dateTime==pItem->m_dateTime && mapItem->HasMusicInfoTag() && mapItem->GetMusicInfoTag()->Loaded()) { // Query map if we previously cached the file on HD *pItem->GetMusicInfoTag() = *mapItem->GetMusicInfoTag(); if (mapItem->HasArt("thumb")) pItem->SetArt("thumb", mapItem->GetArt("thumb")); } else { std::string strPath = URIUtils::GetDirectory(pItem->GetPath()); URIUtils::AddSlashAtEnd(strPath); if (strPath!=m_strPrevPath) { // The item is from another directory as the last one, // query the database for the new directory... m_musicDatabase.GetSongsByPath(strPath, m_songsMap); m_databaseHits++; } /* Note for songs from embedded or separate cuesheets strFileName is not unique, so only the first song from such a file gets added to the song map. Any such songs from a cuesheet can be identified by having a non-zero offset value. When the item we are looking up has a cue document or is a music file with a cuesheet embedded in the tags, it needs to have the cuesheet fully processed replacing that item with items for every track etc. This is done elsewhere, as changes to the list of items is not possible from here. This method only loads the item with the song from the database when it maps to a single song. */ MAPSONGS::iterator it = m_songsMap.find(pItem->GetPath()); if (it != m_songsMap.end() && !pItem->HasCueDocument() && it->second.iStartOffset == 0 && it->second.iEndOffset == 0) { // Have we loaded this item from database before (and it is not a cuesheet nor has an embedded cue sheet) pItem->GetMusicInfoTag()->SetSong(it->second); if (!it->second.strThumb.empty()) pItem->SetArt("thumb", it->second.strThumb); } else if (pItem->IsMusicDb()) { // a music db item that doesn't have tag loaded - grab details from the database XFILE::MUSICDATABASEDIRECTORY::CQueryParams param; XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(pItem->GetPath(),param); CSong song; if (m_musicDatabase.GetSong(param.GetSongId(), song)) { pItem->GetMusicInfoTag()->SetSong(song); if (!song.strThumb.empty()) pItem->SetArt("thumb", song.strThumb); } } else if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MUSICFILES_USETAGS) || pItem->IsCDDA()) { // Nothing found, load tag from file, // always try to load cddb info // get correct tag parser std::unique_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(*pItem)); if (NULL != pLoader.get()) // get tag pLoader->Load(pItem->GetPath(), *pItem->GetMusicInfoTag()); m_tagReads++; } m_strPrevPath = strPath; } } return true; }