void CMusicInfoTag::SetAlbum(const CAlbum& album) { //Set all artist infomation from album artist credits and artist description SetArtistDesc(album.strArtistDesc); SetArtist(album.GetAlbumArtist()); SetMusicBrainzArtistID(album.GetMusicBrainzAlbumArtistID()); SetAlbumArtistDesc(album.strArtistDesc); SetAlbumArtist(album.GetAlbumArtist()); SetMusicBrainzAlbumArtistID(album.GetMusicBrainzAlbumArtistID()); SetAlbumId(album.idAlbum); SetAlbum(album.strAlbum); SetTitle(album.strAlbum); SetMusicBrainzAlbumID(album.strMusicBrainzAlbumID); SetGenre(album.genre); SetMood(StringUtils::Join(album.moods, g_advancedSettings.m_musicItemSeparator)); SetRating('0' + album.iRating); SetCompilation(album.bCompilation); SYSTEMTIME stTime; stTime.wYear = album.iYear; SetReleaseDate(stTime); SetAlbumReleaseType(album.releaseType); SetDateAdded(album.dateAdded); SetPlayCount(album.iTimesPlayed); SetDatabaseId(album.idAlbum, MediaTypeAlbum); SetLoaded(); }
void CAddMusicAlbum::OnCommandCharSelector(SallyAPI::GUI::CGUIBaseObject* reporter) { std::string temp = reporter->GetText(); if (temp.length() <= 0) return; char searchForChar = temp[0]; // go to the top if (searchForChar == '*') { ResetImages(); UpdateImages(); return; } int newPosition = 0; std::vector<CAlbum*>::iterator iter = m_vAlbumList.begin(); while (iter != m_vAlbumList.end()) { CAlbum* item = *iter; temp = item->GetArtist(); if (temp.length() > 0) { temp = SallyAPI::String::StringHelper::StringToUpper(temp); char c = temp[0]; if (searchForChar == c) { // found!!!! newPosition = newPosition / m_iRows; m_iStartPicture = newPosition; UpdateImages(); return; } if (((c > searchForChar) && ((c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122))) || (((searchForChar == 48 && searchForChar == 57)) && ((c >= 32 && c <= 47) || (c >= 58 && c <= 64) || (c >= 91 && c <= 96) || (c >= 123 && c <= 126)))) { // ok, we already at the next char newPosition = newPosition / m_iRows; m_iStartPicture = newPosition; UpdateImages(); return; } } ++newPosition; ++iter; } // not found... go to the last one newPosition = newPosition / m_iRows; m_iStartPicture = newPosition; UpdateImages(); }
bool CAudioLibrary::FillFileItem(const std::string &strFilename, CFileItemPtr &item, const CVariant ¶meterObject /* = CVariant(CVariant::VariantTypeArray) */) { CMusicDatabase musicdatabase; if (strFilename.empty()) return false; bool filled = false; if (musicdatabase.Open()) { if (CDirectory::Exists(strFilename)) { CAlbum album; int albumid = musicdatabase.GetAlbumIdByPath(strFilename); if (musicdatabase.GetAlbum(albumid, album, false)) { item->SetFromAlbum(album); FillItemArtistIDs(album.GetArtistIDArray(), item); CFileItemList items; items.Add(item); if (GetAdditionalAlbumDetails(parameterObject, items, musicdatabase) == OK) filled = true; } } else { CSong song; if (musicdatabase.GetSongByFileName(strFilename, song)) { item->SetFromSong(song); FillItemArtistIDs(song.GetArtistIDArray(), item); CFileItemList items; items.Add(item); if (GetAdditionalSongDetails(parameterObject, items, musicdatabase) == OK) filled = true; } } } if (item->GetLabel().empty()) { item->SetLabel(CUtil::GetTitleFromPath(strFilename, false)); if (item->GetLabel().empty()) item->SetLabel(URIUtils::GetFileName(strFilename)); } return filled; }
CAlbum CPFCManager::GetAlbumInfo(const CStdString& strPath) { CAlbum resultAlbum; TiXmlDocument xmlDocument; if (!GetDefsFile(strPath, xmlDocument)) return resultAlbum; TiXmlElement *artistElement = xmlDocument.RootElement()->FirstChildElement("artist"); if (artistElement) { resultAlbum.Load(artistElement->FirstChildElement("album"), true, true); } return resultAlbum; }
void CAudioLibrary::FillAlbumItem(const CAlbum &album, const std::string &path, CFileItemPtr &item) { item = CFileItemPtr(new CFileItem(path, album)); // Add album artistIds as separate property as not part of CMusicInfoTag std::vector<int> artistids = album.GetArtistIDArray(); FillItemArtistIDs(artistids, item); }
INFO_RET CMusicInfoScanner::UpdateDatabaseAlbumInfo(CAlbum& album, const ADDON::ScraperPtr& scraper, bool bAllowSelection, CGUIDialogProgress* pDialog /* = NULL */) { if (!scraper) return INFO_ERROR; CMusicAlbumInfo albumInfo; loop: CLog::Log(LOGDEBUG, "%s downloading info for: %s", __FUNCTION__, album.strAlbum.c_str()); INFO_RET albumDownloadStatus = DownloadAlbumInfo(album, scraper, albumInfo, pDialog); if (albumDownloadStatus == INFO_NOT_FOUND) { if (pDialog && bAllowSelection) { if (!CGUIKeyboardFactory::ShowAndGetInput(album.strAlbum, CVariant{g_localizeStrings.Get(16011)}, false)) return INFO_CANCELLED; std::string strTempArtist(album.GetAlbumArtistString()); if (!CGUIKeyboardFactory::ShowAndGetInput(strTempArtist, CVariant{g_localizeStrings.Get(16025)}, false)) return INFO_CANCELLED; album.strArtistDesc = strTempArtist; goto loop; } else { CEventLog::GetInstance().Add(EventPtr(new CMediaLibraryEvent( MediaTypeAlbum, album.strPath, 24146, StringUtils::Format(g_localizeStrings.Get(24147).c_str(), MediaTypeAlbum, album.strAlbum.c_str()), CScraperUrl::GetThumbURL(album.thumbURL.GetFirstThumb()), CURL::GetRedacted(album.strPath), EventLevel::Warning))); } } else if (albumDownloadStatus == INFO_ADDED) { bool overridetags = CServiceBroker::GetSettings().GetBool(CSettings::SETTING_MUSICLIBRARY_OVERRIDETAGS); album.MergeScrapedAlbum(albumInfo.GetAlbum(), overridetags); m_musicDatabase.Open(); m_musicDatabase.UpdateAlbum(album, overridetags); GetAlbumArtwork(album.idAlbum, album); m_musicDatabase.Close(); albumInfo.SetLoaded(true); } return albumDownloadStatus; }
INFO_RET CMusicInfoScanner::UpdateDatabaseAlbumInfo(CAlbum& album, const ADDON::ScraperPtr& scraper, bool bAllowSelection, CGUIDialogProgress* pDialog /* = NULL */) { if (!scraper) return INFO_ERROR; CMusicAlbumInfo albumInfo; loop: CLog::Log(LOGDEBUG, "%s downloading info for: %s", __FUNCTION__, album.strAlbum.c_str()); INFO_RET albumDownloadStatus = DownloadAlbumInfo(album, scraper, albumInfo, pDialog); if (albumDownloadStatus == INFO_NOT_FOUND) { if (pDialog && bAllowSelection) { if (!CGUIKeyboardFactory::ShowAndGetInput(album.strAlbum, g_localizeStrings.Get(16011), false)) return INFO_CANCELLED; std::string strTempArtist(StringUtils::Join(album.artist, g_advancedSettings.m_musicItemSeparator)); if (!CGUIKeyboardFactory::ShowAndGetInput(strTempArtist, g_localizeStrings.Get(16025), false)) return INFO_CANCELLED; album.artist = StringUtils::Split(strTempArtist, g_advancedSettings.m_musicItemSeparator); goto loop; } } else if (albumDownloadStatus == INFO_ADDED) { album.MergeScrapedAlbum(albumInfo.GetAlbum(), CSettings::Get().GetBool("musiclibrary.overridetags")); m_musicDatabase.Open(); m_musicDatabase.UpdateAlbum(album); GetAlbumArtwork(album.idAlbum, album); m_musicDatabase.Close(); albumInfo.SetLoaded(true); } return albumDownloadStatus; }
void CAddMusicAlbum::OnCommandAddAlbum(int reporterId) { if (reporterId == 0) return; reporterId = reporterId - 1; int col = reporterId / 100; int row = reporterId % 100; std::vector<SallyAPI::GUI::CImageBox*> imageBoxVector = m_mImage[col]; std::vector<SallyAPI::GUI::CLabelBox*> imageNameVector = m_mImageName[col]; int fileID = (m_iStartPicture * m_iRows) + (col * m_iRows) + row - m_iRows; if (fileID >= m_vAlbumList.size()) return; CAlbum* album = m_vAlbumList[fileID]; CMediaDatabase::GetAlbumTitelsFromDatabase(dynamic_cast<SallyAPI::GUI::CAppBase*> (m_pParent), m_pAlbumTitles, album->GetAlbum(), album->GetArtist()); AddAllToPlaylistFromListView(); }
void CGUIWindowMusicBase::UpdateThumb(const CAlbum &album, const std::string &path) { // check user permissions bool saveDb = album.idAlbum != -1; bool saveDirThumb = true; if (!CProfilesManager::GetInstance().GetCurrentProfile().canWriteDatabases() && !g_passwordManager.bMasterUser) { saveDb = false; saveDirThumb = false; } std::string albumThumb = m_musicdatabase.GetArtForItem(album.idAlbum, MediaTypeAlbum, "thumb"); // Update the thumb in the music database (songs + albums) std::string albumPath(path); if (saveDb && CFile::Exists(albumThumb)) m_musicdatabase.SaveAlbumThumb(album.idAlbum, albumThumb); // Update currently playing song if it's from the same album. This is necessary as when the album // first gets it's cover, the info manager's item doesn't have the updated information (so will be // sending a blank thumb to the skin.) if (g_application.m_pPlayer->IsPlayingAudio()) { const CMusicInfoTag* tag=g_infoManager.GetCurrentSongTag(); if (tag) { // really, this may not be enough as it is to reliably update this item. eg think of various artists albums // that aren't tagged as such (and aren't yet scanned). But we probably can't do anything better than this // in that case if (album.strAlbum == tag->GetAlbum() && (album.GetAlbumArtist() == tag->GetAlbumArtist() || album.GetAlbumArtist() == tag->GetArtist())) { g_infoManager.SetCurrentAlbumThumb(albumThumb); } } } // Save this thumb as the directory thumb if it's the only album in the folder (files view nicety) // We do this by grabbing all the songs in the folder, and checking to see whether they come // from the same album. if (saveDirThumb && CFile::Exists(albumThumb) && !albumPath.empty() && !URIUtils::IsCDDA(albumPath)) { CFileItemList items; GetDirectory(albumPath, items); OnRetrieveMusicInfo(items); VECALBUMS albums; CMusicInfoScanner::FileItemsToAlbums(items, albums); if (albums.size() == 1) { // set as folder thumb as well CMusicThumbLoader loader; loader.SetCachedImage(items, "thumb", albumPath); } } // update the file listing - we have to update the whole lot, as it's likely that // more than just our thumbnails changed //! @todo Ideally this would only be done when needed - at the moment we appear to be //! doing this for every lookup, possibly twice (see ShowAlbumInfo) Refresh(true); // Do we have to autoswitch to the thumb control? m_guiState.reset(CGUIViewState::GetViewState(GetID(), *m_vecItems)); UpdateButtons(); }
JSONRPC_STATUS CAudioLibrary::SetAlbumDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { int id = (int)parameterObject["albumid"].asInteger(); CMusicDatabase musicdatabase; if (!musicdatabase.Open()) return InternalError; CAlbum album; // Get current album details, but not songs as we do not want to update them here if (!musicdatabase.GetAlbum(id, album, false) || album.idAlbum <= 0) return InvalidParams; if (ParameterNotNull(parameterObject, "title")) album.strAlbum = parameterObject["title"].asString(); if (ParameterNotNull(parameterObject, "displayartist")) album.strArtistDesc = parameterObject["displayartist"].asString(); // Set album sort string before processing artist credits if (ParameterNotNull(parameterObject, "sortartist")) album.strArtistSort = parameterObject["sortartist"].asString(); // Match up artist names and mbids to make new artist credits // Mbid values only apply if there are names if (ParameterNotNull(parameterObject, "artist")) { std::vector<std::string> artists; std::vector<std::string> mbids; CopyStringArray(parameterObject["artist"], artists); // Check for Musicbrainz ids if (ParameterNotNull(parameterObject, "musicbrainzalbumartistid")) CopyStringArray(parameterObject["musicbrainzalbumartistid"], mbids); // When display artist is not provided and yet artists is changing make by concatenation if (!ParameterNotNull(parameterObject, "displayartist")) album.strArtistDesc = StringUtils::Join(artists, g_advancedSettings.m_musicItemSeparator); album.SetArtistCredits(artists, std::vector<std::string>(), mbids); // On updatealbum artists will be changed album.bArtistSongMerge = true; } if (ParameterNotNull(parameterObject, "description")) album.strReview = parameterObject["description"].asString(); if (ParameterNotNull(parameterObject, "genre")) CopyStringArray(parameterObject["genre"], album.genre); if (ParameterNotNull(parameterObject, "theme")) CopyStringArray(parameterObject["theme"], album.themes); if (ParameterNotNull(parameterObject, "mood")) CopyStringArray(parameterObject["mood"], album.moods); if (ParameterNotNull(parameterObject, "style")) CopyStringArray(parameterObject["style"], album.styles); if (ParameterNotNull(parameterObject, "type")) album.strType = parameterObject["type"].asString(); if (ParameterNotNull(parameterObject, "albumlabel")) album.strLabel = parameterObject["albumlabel"].asString(); if (ParameterNotNull(parameterObject, "rating")) album.fRating = parameterObject["rating"].asFloat(); if (ParameterNotNull(parameterObject, "userrating")) album.iUserrating = parameterObject["userrating"].asInteger(); if (ParameterNotNull(parameterObject, "votes")) album.iVotes = parameterObject["votes"].asInteger(); if (ParameterNotNull(parameterObject, "year")) album.iYear = (int)parameterObject["year"].asInteger(); if (ParameterNotNull(parameterObject, "musicbrainzalbumid")) album.strMusicBrainzAlbumID = parameterObject["musicbrainzalbumid"].asString(); if (ParameterNotNull(parameterObject, "musicbrainzreleasegroupid")) album.strReleaseGroupMBID = parameterObject["musicbrainzreleasegroupid"].asString(); // Update existing art. Any existing artwork that isn't specified in this request stays as is. // If the value is null then the existing art with that type is removed. if (ParameterNotNull(parameterObject, "art")) { // Get current artwork musicdatabase.GetArtForItem(album.idAlbum, MediaTypeAlbum, album.art); std::set<std::string> removedArtwork; CVariant art = parameterObject["art"]; for (CVariant::const_iterator_map artIt = art.begin_map(); artIt != art.end_map(); artIt++) { if (artIt->second.isString() && !artIt->second.asString().empty()) album.art[artIt->first] = CTextureUtils::UnwrapImageURL(artIt->second.asString()); else if (artIt->second.isNull()) { album.art.erase(artIt->first); removedArtwork.insert(artIt->first); } } // Remove null art now, as not done by update if (!musicdatabase.RemoveArtForItem(album.idAlbum, MediaTypeAlbum, removedArtwork)) return InternalError; } // Update artist including adding or replacing (but not removing) art if (!musicdatabase.UpdateAlbum(album)) return InternalError; CJSONRPCUtils::NotifyItemUpdated(); return ACK; }
void CMusicInfoScanner::Process() { ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnScanStarted"); try { if (m_showDialog && !CServiceBroker::GetSettings().GetBool(CSettings::SETTING_MUSICLIBRARY_BACKGROUNDUPDATE)) { CGUIDialogExtendedProgressBar* dialog = g_windowManager.GetWindow<CGUIDialogExtendedProgressBar>(WINDOW_DIALOG_EXT_PROGRESS); if (dialog) m_handle = dialog->GetHandle(g_localizeStrings.Get(314)); } // check if we only need to perform a cleaning if (m_bClean && m_pathsToScan.empty()) { CleanDatabase(false); m_handle = NULL; m_bRunning = false; return; } unsigned int tick = XbmcThreads::SystemClockMillis(); m_musicDatabase.Open(); m_bCanInterrupt = true; if (m_scanType == 0) // load info from files { CLog::Log(LOGDEBUG, "%s - Starting scan", __FUNCTION__); if (m_handle) m_handle->SetTitle(g_localizeStrings.Get(505)); // Reset progress vars m_currentItem=0; m_itemCount=-1; // Create the thread to count all files to be scanned SetPriority( GetMinPriority() ); if (m_handle) m_fileCountReader.Create(); // Database operations should not be canceled // using Interrupt() while scanning as it could // result in unexpected behaviour. m_bCanInterrupt = false; m_needsCleanup = false; bool commit = true; for (std::set<std::string>::const_iterator it = m_pathsToScan.begin(); it != m_pathsToScan.end(); ++it) { if (!CDirectory::Exists(*it) && !m_bClean) { /* * Note that this will skip scanning (if m_bClean is disabled) if the directory really * doesn't exist. Since the music scanner is fed with a list of existing paths from the DB * and cleans out all songs under that path as its first step before re-adding files, if * the entire source is offline we totally empty the music database in one go. */ CLog::Log(LOGWARNING, "%s directory '%s' does not exist - skipping scan.", __FUNCTION__, it->c_str()); m_seenPaths.insert(*it); continue; } else if (!DoScan(*it)) { commit = false; break; } } if (commit) { g_infoManager.ResetLibraryBools(); if (m_needsCleanup) { if (m_handle) { m_handle->SetTitle(g_localizeStrings.Get(700)); m_handle->SetText(""); } m_musicDatabase.CleanupOrphanedItems(); if (m_handle) m_handle->SetTitle(g_localizeStrings.Get(331)); m_musicDatabase.Compress(false); } } m_fileCountReader.StopThread(); m_musicDatabase.EmptyCache(); tick = XbmcThreads::SystemClockMillis() - tick; CLog::Log(LOGNOTICE, "My Music: Scanning for music info using worker thread, operation took %s", StringUtils::SecondsToTimeString(tick / 1000).c_str()); } if (m_scanType == 1) // load album info { for (std::set<std::string>::const_iterator it = m_pathsToScan.begin(); it != m_pathsToScan.end(); ++it) { CQueryParams params; CDirectoryNode::GetDatabaseInfo(*it, params); if (m_musicDatabase.HasAlbumBeenScraped(params.GetAlbumId())) // should this be here? continue; CAlbum album; m_musicDatabase.GetAlbum(params.GetAlbumId(), album); if (m_handle) { float percentage = (float) std::distance(it, m_pathsToScan.end()) / m_pathsToScan.size(); m_handle->SetText(album.GetAlbumArtistString() + " - " + album.strAlbum); m_handle->SetPercentage(percentage); } // find album info ADDON::ScraperPtr scraper; if (!m_musicDatabase.GetScraperForPath(*it, scraper, ADDON::ADDON_SCRAPER_ALBUMS)) continue; UpdateDatabaseAlbumInfo(album, scraper, false); if (m_bStop) break; } } if (m_scanType == 2) // load artist info { for (std::set<std::string>::const_iterator it = m_pathsToScan.begin(); it != m_pathsToScan.end(); ++it) { CQueryParams params; CDirectoryNode::GetDatabaseInfo(*it, params); if (m_musicDatabase.HasArtistBeenScraped(params.GetArtistId())) // should this be here? continue; CArtist artist; m_musicDatabase.GetArtist(params.GetArtistId(), artist); m_musicDatabase.GetArtistPath(params.GetArtistId(), artist.strPath); if (m_handle) { float percentage = (float) (std::distance(m_pathsToScan.begin(), it) / m_pathsToScan.size()) * 100; m_handle->SetText(artist.strArtist); m_handle->SetPercentage(percentage); } // find album info ADDON::ScraperPtr scraper; if (!m_musicDatabase.GetScraperForPath(*it, scraper, ADDON::ADDON_SCRAPER_ARTISTS) || !scraper) continue; UpdateDatabaseArtistInfo(artist, scraper, false); if (m_bStop) break; } } } catch (...) { CLog::Log(LOGERROR, "MusicInfoScanner: Exception while scanning."); } m_musicDatabase.Close(); CLog::Log(LOGDEBUG, "%s - Finished scan", __FUNCTION__); m_bRunning = false; ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnScanFinished"); // we need to clear the musicdb cache and update any active lists CUtil::DeleteMusicDatabaseDirectoryCache(); CGUIMessage msg(GUI_MSG_SCAN_FINISHED, 0, 0, 0); g_windowManager.SendThreadMessage(msg); if (m_handle) m_handle->MarkFinished(); m_handle = NULL; }
INFO_RET CMusicInfoScanner::DownloadAlbumInfo(const CAlbum& album, const ADDON::ScraperPtr& info, CMusicAlbumInfo& albumInfo, CGUIDialogProgress* pDialog) { if (m_handle) { m_handle->SetTitle(StringUtils::Format(g_localizeStrings.Get(20321).c_str(), info->Name().c_str())); m_handle->SetText(album.GetAlbumArtistString() + " - " + album.strAlbum); } // clear our scraper cache info->ClearCache(); CMusicInfoScraper scraper(info); bool bMusicBrainz = false; if (!album.strMusicBrainzAlbumID.empty()) { CScraperUrl musicBrainzURL; if (ResolveMusicBrainz(album.strMusicBrainzAlbumID, info, musicBrainzURL)) { CMusicAlbumInfo albumNfo("nfo", musicBrainzURL); scraper.GetAlbums().clear(); scraper.GetAlbums().push_back(albumNfo); bMusicBrainz = true; } } // handle nfo files std::string path = album.strPath; if (path.empty()) m_musicDatabase.GetAlbumPath(album.idAlbum, path); std::string strNfo = URIUtils::AddFileToFolder(path, "album.nfo"); CNfoFile::NFOResult result = CNfoFile::NO_NFO; CNfoFile nfoReader; if (XFILE::CFile::Exists(strNfo)) { CLog::Log(LOGDEBUG,"Found matching nfo file: %s", CURL::GetRedacted(strNfo).c_str()); result = nfoReader.Create(strNfo, info); if (result == CNfoFile::FULL_NFO) { CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__); nfoReader.GetDetails(albumInfo.GetAlbum()); return INFO_ADDED; } else if (result == CNfoFile::URL_NFO || result == CNfoFile::COMBINED_NFO) { CScraperUrl scrUrl(nfoReader.ScraperUrl()); CMusicAlbumInfo albumNfo("nfo",scrUrl); ADDON::ScraperPtr nfoReaderScraper = nfoReader.GetScraperInfo(); CLog::Log(LOGDEBUG,"-- nfo-scraper: %s", nfoReaderScraper->Name().c_str()); CLog::Log(LOGDEBUG,"-- nfo url: %s", scrUrl.m_url[0].m_url.c_str()); scraper.SetScraperInfo(nfoReaderScraper); scraper.GetAlbums().clear(); scraper.GetAlbums().push_back(albumNfo); } else if (result != CNfoFile::PARTIAL_NFO) CLog::Log(LOGERROR,"Unable to find an url in nfo file: %s", strNfo.c_str()); } if (!scraper.CheckValidOrFallback(CServiceBroker::GetSettings().GetString(CSettings::SETTING_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 INFO_ERROR; } if (!scraper.GetAlbumCount()) { scraper.FindAlbumInfo(album.strAlbum, album.GetAlbumArtistString()); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); return INFO_CANCELLED; } Sleep(1); } } CGUIDialogSelect *pDlg = NULL; int iSelectedAlbum=0; if ((result == CNfoFile::NO_NFO || result == CNfoFile::PARTIAL_NFO) && !bMusicBrainz) { iSelectedAlbum = -1; // set negative so that we can detect a failure if (scraper.Succeeded() && scraper.GetAlbumCount() >= 1) { double bestRelevance = 0; double minRelevance = THRESHOLD; if (scraper.GetAlbumCount() > 1) // score the matches { //show dialog with all albums found if (pDialog) { pDlg = g_windowManager.GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT); pDlg->SetHeading(CVariant{g_localizeStrings.Get(181)}); 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, album.strAlbum, info.GetAlbum().GetAlbumArtistString(), album.GetAlbumArtistString()); // 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 >= std::max(minRelevance, bestRelevance)) { // we auto-select the best of these bestRelevance = relevance; iSelectedAlbum = i; } if (pDialog) { // set the label to [relevance] album - artist std::string strTemp = StringUtils::Format("[%0.2f] %s", relevance, info.GetTitle2().c_str()); 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; } if (pDialog && bestRelevance < THRESHOLD) { pDlg->Sort(false); pDlg->Open(); // and wait till user selects one if (pDlg->GetSelectedItem() < 0) { // none chosen if (!pDlg->IsButtonPressed()) return INFO_CANCELLED; // manual button pressed std::string strNewAlbum = album.strAlbum; if (!CGUIKeyboardFactory::ShowAndGetInput(strNewAlbum, CVariant{g_localizeStrings.Get(16011)}, false)) return INFO_CANCELLED; if (strNewAlbum == "") return INFO_CANCELLED; std::string strNewArtist = album.GetAlbumArtistString(); if (!CGUIKeyboardFactory::ShowAndGetInput(strNewArtist, CVariant{g_localizeStrings.Get(16025)}, false)) return INFO_CANCELLED; pDialog->SetLine(0, CVariant{strNewAlbum}); pDialog->SetLine(1, CVariant{strNewArtist}); pDialog->Progress(); CAlbum newAlbum = album; newAlbum.strAlbum = strNewAlbum; newAlbum.strArtistDesc = strNewArtist; return DownloadAlbumInfo(newAlbum, info, albumInfo, pDialog); } iSelectedAlbum = pDlg->GetSelectedFileItem()->m_idepth; } } else { CMusicAlbumInfo& info = scraper.GetAlbum(0); double relevance = info.GetRelevance(); if (relevance < 0) relevance = CUtil::AlbumRelevance(info.GetAlbum().strAlbum, album.strAlbum, info.GetAlbum().GetAlbumArtistString(), album.GetAlbumArtistString()); if (relevance < THRESHOLD) return INFO_NOT_FOUND; iSelectedAlbum = 0; } } if (iSelectedAlbum < 0) return INFO_NOT_FOUND; } scraper.LoadAlbumInfo(iSelectedAlbum); while (!scraper.Completed()) { if (m_bStop) { scraper.Cancel(); return INFO_CANCELLED; } Sleep(1); } if (!scraper.Succeeded()) return INFO_ERROR; albumInfo = scraper.GetAlbum(iSelectedAlbum); if (result == CNfoFile::COMBINED_NFO || result == CNfoFile::PARTIAL_NFO) nfoReader.GetDetails(albumInfo.GetAlbum(), NULL, true); return INFO_ADDED; }
void CGetCovers::RunEx() { std::vector<CAlbum*> albumList; CMediaDatabase::GetAlbumsFromDatabaseNotLoaded(m_pWindow, &albumList); // set processbar max m_pProcessbar->SetMaxPosition((int) albumList.size()); std::vector<CAlbum*>::iterator iter = albumList.begin(); while ((iter != albumList.end()) && (!m_bPleaseStop)) { CAlbum* album = *iter; std::string outfile = SallyAPI::String::PathHelper::GetDirectoryFromPath(album->GetFilename()); outfile.append(album->GetCoverName()); bool exists = SallyAPI::File::FileHelper::FileExists(outfile); if (exists) { // Datei exists already CMediaDatabase::SetAlbumInDatabase(m_pWindow, album->GetAlbum(), album->GetArtist(), true); } else { // Get it from Amazon bool result = false; result = m_AmazonCover.GetMusicCover(album->GetArtist(), album->GetAlbum(), outfile); if (result) { CMediaDatabase::SetAlbumInDatabase(m_pWindow, album->GetAlbum(), album->GetArtist(), true); } else { CMediaDatabase::SetAlbumInDatabase(m_pWindow, album->GetAlbum(), album->GetArtist(), false); } } ++iter; // update processbar m_pProcessbar->SetPosition(m_pProcessbar->GetPosition() + 1); } // Delete vector iter = albumList.begin(); while (iter != albumList.end()) { SafeDelete(*iter); ++iter; } if (!m_bPleaseStop) m_pWindow->SendMessageToParent(0, 0, m_iMessageId); }
void CAddMusicAlbum::OnCommandProcessClicked(int reporterId) { if (reporterId == 0) return; reporterId = reporterId - 1; int col = reporterId / 100; int row = reporterId % 100; std::vector<SallyAPI::GUI::CImageBox*> imageBoxVector = m_mImage[col]; std::vector<SallyAPI::GUI::CLabelBox*> imageNameVector = m_mImageName[col]; int fileID = (m_iStartPicture * m_iRows) + (col * m_iRows) + row - m_iRows; CAlbum* album = m_vAlbumList[fileID]; m_tAlbumGetter.SetValues(dynamic_cast<SallyAPI::GUI::CAppBase*> (m_pParent), m_pAlbumTitles, album->GetAlbum(), album->GetArtist()); m_tAlbumGetter.Start(); m_pSmoothMoveForm->Enable(false); m_pFilterBackground->Enable(false); for (int i = 0; i < 28; ++i) { m_pCharSelector[i]->Enable(false); } // Set Album und Artist std::string temp = album->GetAlbum(); temp.append("\n"); temp.append(album->GetArtist()); m_pAlbumName->SetText(temp); // move speed int xDistance = imageBoxVector[row]->GetPositionX() - (m_pAlbumBackground->GetPositionX() + 5); int yDistance = imageBoxVector[row]->GetPositionY() - (m_pAlbumBackground->GetPositionY() + 5); int widthDistance = (510 - 10) - imageBoxVector[row]->GetWidth(); int heightDistance = (510 - 10) - imageBoxVector[row]->GetHeight(); if (xDistance < 0) xDistance *= -1; if (yDistance < 0) yDistance *= -1; if (widthDistance < 0) widthDistance *= -1; if (heightDistance < 0) heightDistance *= -1; int speedX = (int) (600 * (float) ((float) xDistance / (float) widthDistance)); int speedY = (int) (600 * (float) ((float) yDistance / (float) widthDistance)); m_pImageBoxBig->Move(imageBoxVector[row]->GetPositionX(), imageBoxVector[row]->GetPositionY()); m_pImageBoxBig->Resize(imageBoxVector[row]->GetWidth(), imageBoxVector[row]->GetHeight()); m_pImageBoxBig->MoveAnimated(m_pAlbumBackground->GetPositionX() + 5, m_pAlbumBackground->GetPositionY() + 5, speedX, speedY); m_pImageBoxBig->ResizeAnimated(510 - 10, 510 - 10, 600); m_pImageBoxBig->SetPicture(imageBoxVector[row]->GetPicture()); m_pImageBoxBig->SetRotationAngleY(0.0f); m_pImageBoxBig->SetStopAngelY(180); m_pImageBoxBig->RotateAnimatedY(6, false); m_pImageBoxBig->Visible(true); m_pZoomBackground->Visible(true); m_pZoomBackground->SetAlphaBlending(0); m_pZoomBackground->BlendAnimated(255, 800); }
void CAddMusicAlbum::UpdateImages() { EnterRenderLock(); SallyAPI::Config::CConfig* config = SallyAPI::Config::CConfig::GetInstance(); SallyAPI::Config::CTheme* theme = config->GetTheme(); std::vector<CAlbum*>::iterator iter = m_vAlbumList.begin(); int k = 0; int i = 0; if (m_iStartPicture == 0) { std::vector<SallyAPI::GUI::CImageBox*> imageBoxVector = m_mImage[0]; std::vector<SallyAPI::GUI::CLabelBox*> imageNameVector = m_mImageName[0]; std::vector<SallyAPI::GUI::CButton*> imageAddAllVector = m_mImageAddAlbum[0]; for (int l = 0; l < m_iRows; ++l) { imageBoxVector[l]->Visible(false); imageNameVector[l]->Visible(false); imageAddAllVector[l]->Visible(false); } k = 1; } for (int l = 0; (l < (m_iStartPicture - 1) * m_iRows) && (iter != m_vAlbumList.end()); ++l) { ++iter; } SallyAPI::GUI::CPicture* picture; while ((k < m_iCols + 2) && (iter != m_vAlbumList.end())) { std::vector<SallyAPI::GUI::CImageBox*> imageBoxVector = m_mImage[k]; std::vector<SallyAPI::GUI::CLabelBox*> imageNameVector = m_mImageName[k]; std::vector<SallyAPI::GUI::CButton*> imageAddAllVector = m_mImageAddAlbum[k]; for (; (i < m_iRows) && (iter != m_vAlbumList.end()); i++) { CAlbum* album = *iter; std::string covername = album->GetCoverName(); std::string filename = SallyAPI::String::PathHelper::GetDirectoryFromPath(album->GetFilename()); filename = SallyAPI::String::PathHelper::CorrectPath(filename); filename.append(covername); std::string description = album->GetArtist(); description.append("\n"); description.append(album->GetAlbum()); imageNameVector[i]->SetText(description); imageBoxVector[i]->SetText(filename); picture = m_mPictureMap[filename]; // Not yet loaded... use default pic if (picture == NULL) picture = theme->GetPicture(GUI_APP_DEFAULT_CD + m_iGraphicId); // Now paint if (picture != NULL) { imageBoxVector[i]->SetPicture(picture); imageBoxVector[i]->Visible(true); /* int xImageBox = 0; int yImageBox = 0; imageBoxVector[i]->GetAbsolutPosition(&xImageBox, &yImageBox); float rotationAngleY = xImageBox - ((WINDOW_WIDTH) / 2) + MENU_WIDTH; rotationAngleY = rotationAngleY / 1500; imageBoxVector[i]->SetRotationAngleY(rotationAngleY); */ imageNameVector[i]->Visible(true); imageAddAllVector[i]->Visible(true); } else { imageBoxVector[i]->SetPicture(NULL); imageNameVector[i]->SetText(""); imageNameVector[i]->Visible(false); imageAddAllVector[i]->Visible(false); } ++iter; } if (iter != m_vAlbumList.end()) { i = 0; k++; } } for (; k < m_iCols + 2; ++k) { std::vector<SallyAPI::GUI::CImageBox*> imageBoxVector = m_mImage[k]; std::vector<SallyAPI::GUI::CLabelBox*> imageNameVector = m_mImageName[k]; std::vector<SallyAPI::GUI::CButton*> imageAddAllVector = m_mImageAddAlbum[k]; for (; i < m_iRows; ++i) { imageBoxVector[i]->Visible(false); imageNameVector[i]->Visible(false); imageAddAllVector[i]->Visible(false); imageNameVector[i]->SetText(""); imageBoxVector[i]->SetPicture(NULL); } i = 0; } LeaveRenderLock(); }
bool CMusicThumbLoader::FillLibraryArt(CFileItem &item) { /* Called for any item with MusicInfoTag and no art. Items on Genres, Sources and Roles nodes have ID (although items on Years node do not) so check for song/album/artist specifically. Non-library songs (file view) can also have MusicInfoTag but no ID or type */ bool artfound(false); std::vector<ArtForThumbLoader> art; CMusicInfoTag &tag = *item.GetMusicInfoTag(); if (tag.GetDatabaseId() > -1 && (tag.GetType() == MediaTypeSong || tag.GetType() == MediaTypeAlbum || tag.GetType() == MediaTypeArtist)) { // Item in music library, fetch the art m_musicDatabase->Open(); if (tag.GetType() == MediaTypeSong) artfound = m_musicDatabase->GetArtForItem(tag.GetDatabaseId(), tag.GetAlbumId(), -1, false, art); else if (tag.GetType() == MediaTypeAlbum) artfound = m_musicDatabase->GetArtForItem(-1, tag.GetDatabaseId(), -1, false, art); else //Artist artfound = m_musicDatabase->GetArtForItem(-1, -1, tag.GetDatabaseId(), true, art); m_musicDatabase->Close(); } else if (!tag.GetArtist().empty() && (tag.GetType() == MediaTypeNone || tag.GetType() == MediaTypeSong)) { /* Could be non-library song - has musictag but no ID or type (may have thumb already). Try to fetch both song artist(s) and album artist(s) art by artist name, e.g. "artist.thumb", "artist.fanart", "artist.clearlogo", "artist.banner", "artist1.thumb", "artist1.fanart", "artist1.clearlogo", "artist1.banner", "albumartist.thumb", "albumartist.fanart" etc. Set fanart as fallback. */ CSong song; // Try to split song artist names (various tags) into artist credits song.SetArtistCredits(tag.GetArtist(), tag.GetMusicBrainzArtistHints(), tag.GetMusicBrainzArtistID()); if (!song.artistCredits.empty()) { tag.SetType(MediaTypeSong); // Makes "Information" context menu visible m_musicDatabase->Open(); int iOrder = 0; // Song artist art for (const auto& artistCredit : song.artistCredits) { int idArtist = m_musicDatabase->GetArtistByName(artistCredit.GetArtist()); if (idArtist > 0) { std::vector<ArtForThumbLoader> artistart; if (m_musicDatabase->GetArtForItem(-1, -1, idArtist, true, artistart)) { for (auto& artitem : artistart) { if (iOrder > 0) artitem.prefix = StringUtils::Format("artist%i", iOrder); else artitem.prefix = "artist"; } art.insert(art.end(), artistart.begin(), artistart.end()); } } ++iOrder; } // Album artist art if (!tag.GetAlbumArtist().empty() && tag.GetArtistString().compare(tag.GetAlbumArtistString()) != 0) { // Split song artist names correctly into artist credits from various tag // arrays, inc. fallback to song artist names CAlbum album; album.SetArtistCredits(tag.GetAlbumArtist(), tag.GetMusicBrainzAlbumArtistHints(), tag.GetMusicBrainzAlbumArtistID(), tag.GetArtist(), tag.GetMusicBrainzArtistHints(), tag.GetMusicBrainzArtistID()); iOrder = 0; for (const auto& artistCredit : album.artistCredits) { int idArtist = m_musicDatabase->GetArtistByName(artistCredit.GetArtist()); if (idArtist > 0) { std::vector<ArtForThumbLoader> artistart; if (m_musicDatabase->GetArtForItem(-1, -1, idArtist, true, artistart)) { for (auto& artitem : artistart) { if (iOrder > 0) artitem.prefix = StringUtils::Format("albumartist%i", iOrder); else artitem.prefix = "albumartist"; } art.insert(art.end(), artistart.begin(), artistart.end()); } } ++iOrder; } } else { // Replicate the artist art as album artist art std::vector<ArtForThumbLoader> artistart; for (const auto& artitem : art) { ArtForThumbLoader newart; newart.artType = artitem.artType; newart.mediaType = artitem.mediaType; newart.prefix = "album" + artitem.prefix; newart.url = artitem.url; artistart.emplace_back(newart); } art.insert(art.end(), artistart.begin(), artistart.end()); } artfound = !art.empty(); m_musicDatabase->Close(); } } if (artfound) { std::string fanartfallback; bool bDiscSetThumbSet = false; std::map<std::string, std::string> artmap; for (auto artitem : art) { /* Add art to artmap, naming according to media type. For example: artists have "thumb", "fanart", "poster" etc., albums have "thumb", "artist.thumb", "artist.fanart",... "artist1.thumb", "artist1.fanart" etc., songs have "thumb", "album.thumb", "artist.thumb", "albumartist.thumb", "albumartist1.thumb" etc. */ std::string artname; if (tag.GetType() == artitem.mediaType) artname = artitem.artType; else if (artitem.prefix.empty()) artname = artitem.mediaType + "." + artitem.artType; else { if (tag.GetType() == MediaTypeAlbum) StringUtils::Replace(artitem.prefix, "albumartist", "artist"); artname = artitem.prefix + "." + artitem.artType; } artmap.insert(std::make_pair(artname, artitem.url)); // Add fallback art for "thumb" and "fanart" art types only // Set album thumb as the fallback used when song thumb is missing // or use extra album thumb when part of disc set if (tag.GetType() == MediaTypeSong && artitem.mediaType == MediaTypeAlbum) { if (artitem.artType == "thumb" && !bDiscSetThumbSet) item.SetArtFallback(artitem.artType, artname); else if (StringUtils::StartsWith(artitem.artType, "thumb")) { int number = atoi(artitem.artType.substr(5).c_str()); if (number > 0 && tag.GetDiscNumber() == number) { item.SetArtFallback("thumb", artname); bDiscSetThumbSet = true; } } } // For albums and songs set fallback fanart from the artist. // For songs prefer primary song artist over primary albumartist fanart as fallback fanart if (artitem.prefix == "artist" && artitem.artType == "fanart") fanartfallback = artname; if (artitem.prefix == "albumartist" && artitem.artType == "fanart" && fanartfallback.empty()) fanartfallback = artname; } if (!fanartfallback.empty()) item.SetArtFallback("fanart", fanartfallback); item.AppendArt(artmap); } return artfound; }