int CMusicInfoScanner::RetrieveMusicInfo(CFileItemList& items, const CStdString& strDirectory) { CSongMap songsMap; // get all information for all files in current directory from database, and remove them if (m_musicDatabase.RemoveSongsFromPath(strDirectory, songsMap)) m_needsCleanup = true; VECSONGS songsToAdd; CStdStringArray regexps = g_advancedSettings.m_audioExcludeFromScanRegExps; // for every file found, but skip folder for (int i = 0; i < items.Size(); ++i) { CFileItemPtr pItem = items[i]; CStdString strExtension; URIUtils::GetExtension(pItem->GetPath(), strExtension); if (m_bStop) return 0; // Discard all excluded files defined by m_musicExcludeRegExps if (CUtil::ExcludeFileOrFolder(pItem->GetPath(), regexps)) continue; // dont try reading id3tags for folders, playlists or shoutcast streams if (!pItem->m_bIsFolder && !pItem->IsPlayList() && !pItem->IsPicture() && !pItem->IsLyrics() ) { m_currentItem++; // CLog::Log(LOGDEBUG, "%s - Reading tag for: %s", __FUNCTION__, pItem->GetPath().c_str()); // grab info from the song CSong *dbSong = songsMap.Find(pItem->GetPath()); CMusicInfoTag& tag = *pItem->GetMusicInfoTag(); if (!tag.Loaded() ) { // read the tag from a file auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(pItem->GetPath())); if (NULL != pLoader.get()) pLoader->Load(pItem->GetPath(), tag); } // if we have the itemcount, notify our // observer with the progress we made if (m_pObserver && m_itemCount>0) m_pObserver->OnSetProgress(m_currentItem, m_itemCount); if (tag.Loaded()) { CSong song(tag); // ensure our song has a valid filename or else it will assert in AddSong() if (song.strFileName.IsEmpty()) { // copy filename from path in case UPnP or other tag loaders didn't specify one (FIXME?) song.strFileName = pItem->GetPath(); // if we still don't have a valid filename, skip the song if (song.strFileName.IsEmpty()) { // this shouldn't ideally happen! CLog::Log(LOGERROR, "Skipping song since it doesn't seem to have a filename"); continue; } } song.iStartOffset = pItem->m_lStartOffset; song.iEndOffset = pItem->m_lEndOffset; if (dbSong) { // keep the db-only fields intact on rescan... song.iTimesPlayed = dbSong->iTimesPlayed; song.lastPlayed = dbSong->lastPlayed; song.iKaraokeNumber = dbSong->iKaraokeNumber; if (song.rating == '0') song.rating = dbSong->rating; } pItem->SetMusicThumb(); song.strThumb = pItem->GetThumbnailImage(); songsToAdd.push_back(song); // CLog::Log(LOGDEBUG, "%s - Tag loaded for: %s", __FUNCTION__, pItem->GetPath().c_str()); } else CLog::Log(LOGDEBUG, "%s - No tag found for: %s", __FUNCTION__, pItem->GetPath().c_str()); } } CheckForVariousArtists(songsToAdd); if (!items.HasThumbnail()) UpdateFolderThumb(songsToAdd, items.GetPath()); // finally, add these to the database set<CStdString> artistsToScan; set< pair<CStdString, CStdString> > albumsToScan; m_musicDatabase.BeginTransaction(); for (unsigned int i = 0; i < songsToAdd.size(); ++i) { if (m_bStop) { m_musicDatabase.RollbackTransaction(); return i; } CSong &song = songsToAdd[i]; m_musicDatabase.AddSong(song, false); artistsToScan.insert(song.strArtist); albumsToScan.insert(make_pair(song.strAlbum, song.strArtist)); } m_musicDatabase.CommitTransaction(); bool bCanceled; for (set<CStdString>::iterator i = artistsToScan.begin(); i != artistsToScan.end(); ++i) { bCanceled = false; long iArtist = m_musicDatabase.GetArtistByName(*i); if (find(m_artistsScanned.begin(),m_artistsScanned.end(),iArtist) == m_artistsScanned.end()) { m_artistsScanned.push_back(iArtist); if (!m_bStop && g_guiSettings.GetBool("musiclibrary.downloadinfo")) { CStdString strPath; strPath.Format("musicdb://2/%u/",iArtist); if (!DownloadArtistInfo(strPath,*i, bCanceled)) // assume we want to retry m_artistsScanned.pop_back(); } else GetArtistArtwork(iArtist, *i); } } if (g_guiSettings.GetBool("musiclibrary.downloadinfo")) { for (set< pair<CStdString, CStdString> >::iterator i = albumsToScan.begin(); i != albumsToScan.end(); ++i) { if (m_bStop) return songsToAdd.size(); long iAlbum = m_musicDatabase.GetAlbumByName(i->first, i->second); CStdString strPath; strPath.Format("musicdb://3/%u/",iAlbum); bCanceled = false; if (find(m_albumsScanned.begin(), m_albumsScanned.end(), iAlbum) == m_albumsScanned.end()) { CMusicAlbumInfo albumInfo; if (DownloadAlbumInfo(strPath, i->second, i->first, bCanceled, albumInfo)) m_albumsScanned.push_back(iAlbum); } } } if (m_pObserver) m_pObserver->OnStateChanged(READING_MUSIC_INFO); return songsToAdd.size(); }
bool CGUIWindowPrograms::GetDirectory(const CStdString &strDirectory, CFileItemList &items) { bool bFlattened=false; if (URIUtils::IsDVD(strDirectory)) { CStdString strPath; URIUtils::AddFileToFolder(strDirectory,"default.xbe",strPath); if (CFile::Exists(strPath)) // flatten dvd { CFileItemPtr item(new CFileItem("default.xbe")); item->SetPath(strPath); items.Add(item); items.SetPath(strDirectory); bFlattened = true; } } if (!bFlattened) if (!CGUIMediaWindow::GetDirectory(strDirectory, items)) return false; if (items.IsVirtualDirectoryRoot()) { items.SetLabel(""); return true; } if (strDirectory.Equals("plugin://programs/")) { items.SetContent("plugins"); items.SetLabel(g_localizeStrings.Get(24001)); } // flatten any folders m_database.BeginTransaction(); DWORD dwTick=timeGetTime(); bool bProgressVisible = false; for (int i = 0; i < items.Size(); i++) { CStdString shortcutPath; CFileItemPtr item = items[i]; if (!bProgressVisible && timeGetTime()-dwTick>1500 && m_dlgProgress) { // tag loading takes more then 1.5 secs, show a progress dialog m_dlgProgress->SetHeading(189); m_dlgProgress->SetLine(0, 20120); m_dlgProgress->SetLine(1,""); m_dlgProgress->SetLine(2, item->GetLabel()); if (!g_guiSettings.GetBool("mygames.slowgameparsing")) { m_dlgProgress->StartModal(); } bProgressVisible = true; } if (bProgressVisible) { m_dlgProgress->SetLine(2,item->GetLabel()); m_dlgProgress->Progress(); } if (item->m_bIsFolder && !item->IsParentFolder() && !item->IsPlugin() && g_guiSettings.GetBool("mygames.slowgameparsing")) { // folder item - let's check for a default.xbe file, and flatten if we have one CStdString defaultXBE; URIUtils::AddFileToFolder(item->GetPath(), "default.xbe", defaultXBE); item->SetPath(defaultXBE); item->m_bIsFolder = false; } if (item->m_bIsFolder && !item->IsParentFolder() && !item->IsPlugin() && !g_guiSettings.GetBool("mygames.slowgameparsing")) { // folder item - let's check for a default.xbe file, and flatten if we have one CStdString defaultXBE; URIUtils::AddFileToFolder(item->GetPath(), "default.xbe", defaultXBE); if (CFile::Exists(defaultXBE)) { // yes, format the item up item->SetPath(defaultXBE); item->m_bIsFolder = false; } } else if (item->IsShortCut()) { // resolve the shortcut to set it's description etc. // and save the old shortcut path (so we can reassign it later) CShortcut cut; if (cut.Create(item->GetPath())) { shortcutPath = item->GetPath(); item->SetPath(cut.m_strPath); item->SetThumbnailImage(cut.m_strThumb); LABEL_MASKS labelMasks; m_guiState->GetSortMethodLabelMasks(labelMasks); CLabelFormatter formatter("", labelMasks.m_strLabel2File); if (!cut.m_strLabel.IsEmpty()) { item->SetLabel(cut.m_strLabel); __stat64 stat; if (CFile::Stat(item->GetPath(),&stat) == 0) item->m_dwSize = stat.st_size; formatter.FormatLabel2(item.get()); item->SetLabelPreformated(true); } } } if (item->IsXBE()) { if (URIUtils::GetFileName(item->GetPath()).Equals("default_ffp.xbe")) { m_vecItems->Remove(i--); continue; } // add to database if not already there DWORD dwTitleID = item->IsOnDVD() ? 0 : m_database.GetProgramInfo(item.get()); if (!dwTitleID) { CStdString description; if (CUtil::GetXBEDescription(item->GetPath(), description) && (!item->IsLabelPreformated() && !item->GetLabel().IsEmpty())) { item->SetLabel(description); if (!g_guiSettings.GetBool("mygames.slowgameparsing")) { CLog::Log(LOGNOTICE,"Added to database: %s",description.c_str()); } } dwTitleID = CUtil::GetXbeID(item->GetPath()); if (!item->IsOnDVD()) m_database.AddProgramInfo(item.get(), dwTitleID); } // SetOverlayIcons() if (m_database.ItemHasTrainer(dwTitleID)) { if (m_database.GetActiveTrainer(dwTitleID) != "") item->SetOverlayImage(CGUIListItem::ICON_OVERLAY_TRAINED); else item->SetOverlayImage(CGUIListItem::ICON_OVERLAY_HAS_TRAINER); } } if (!shortcutPath.IsEmpty()) item->SetPath(shortcutPath); } m_database.CommitTransaction(); // set the cached thumbs items.SetThumbnailImage(""); items.SetCachedProgramThumbs(); items.SetCachedProgramThumb(); if (!items.HasThumbnail()) items.SetUserProgramThumb(); if (bProgressVisible) m_dlgProgress->Close(); return true; }
int CMusicInfoScanner::RetrieveMusicInfo(CFileItemList& items, const CStdString& strDirectory) { CSongMap songsMap; // get all information for all files in current directory from database, and remove them if (m_musicDatabase.RemoveSongsFromPath(strDirectory, songsMap)) m_needsCleanup = true; VECSONGS songsToAdd; // for every file found, but skip folder for (int i = 0; i < items.Size(); ++i) { CFileItem* pItem = items[i]; CStdString strExtension; CUtil::GetExtension(pItem->m_strPath, strExtension); if (m_bStop) return 0; // dont try reading id3tags for folders, playlists or shoutcast streams if (!pItem->m_bIsFolder && !pItem->IsPlayList() && !pItem->IsShoutCast() && !pItem->IsPicture()) { m_currentItem++; // CLog::Log(LOGDEBUG, "%s - Reading tag for: %s", __FUNCTION__, pItem->m_strPath.c_str()); // grab info from the song CSong *dbSong = songsMap.Find(pItem->m_strPath); CMusicInfoTag& tag = *pItem->GetMusicInfoTag(); if (!tag.Loaded() ) { // read the tag from a file auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(pItem->m_strPath)); if (NULL != pLoader.get()) pLoader->Load(pItem->m_strPath, tag); } // if we have the itemcount, notify our // observer with the progress we made if (m_pObserver && m_itemCount>0) m_pObserver->OnSetProgress(m_currentItem, m_itemCount); if (tag.Loaded()) { CSong song(tag); song.iStartOffset = pItem->m_lStartOffset; song.iEndOffset = pItem->m_lEndOffset; if (dbSong) { // keep the db-only fields intact on rescan... song.iTimesPlayed = dbSong->iTimesPlayed; song.lastPlayed = dbSong->lastPlayed; if (song.rating == '0') song.rating = dbSong->rating; } pItem->SetMusicThumb(); song.strThumb = pItem->GetThumbnailImage(); songsToAdd.push_back(song); // CLog::Log(LOGDEBUG, "%s - Tag loaded for: %s", __FUNCTION__, spItem->m_strPath.c_str()); } else CLog::Log(LOGDEBUG, "%s - No tag found for: %s", __FUNCTION__, pItem->m_strPath.c_str()); } } CheckForVariousArtists(songsToAdd); if (!items.HasThumbnail()) UpdateFolderThumb(songsToAdd, items.m_strPath); // finally, add these to the database for (unsigned int i = 0; i < songsToAdd.size(); ++i) { if (m_bStop) return i; CSong &song = songsToAdd[i]; m_musicDatabase.AddSong(song, false); if (!m_bStop && g_guiSettings.GetBool("musiclibrary.autoartistinfo")) { long iArtist = m_musicDatabase.GetArtistByName(song.strArtist); CStdString strPath; strPath.Format("musicdb://2/%u/",iArtist); if (find(m_artistsScanned.begin(),m_artistsScanned.end(),iArtist) == m_artistsScanned.end()) if (DownloadArtistInfo(strPath,song.strArtist)) m_artistsScanned.push_back(iArtist); if (m_pObserver) m_pObserver->OnStateChanged(READING_MUSIC_INFO); } if (!m_bStop && g_guiSettings.GetBool("musiclibrary.autoalbuminfo")) { long iAlbum = m_musicDatabase.GetAlbumByName(song.strAlbum,song.strArtist); CStdString strPath; strPath.Format("musicdb://3/%u/",iAlbum); CMusicAlbumInfo albumInfo; bool bCanceled; if (find(m_albumsScanned.begin(),m_albumsScanned.end(),iAlbum) == m_albumsScanned.end()) if (DownloadAlbumInfo(strPath,song.strArtist,song.strAlbum,bCanceled,albumInfo)) m_albumsScanned.push_back(iAlbum); if (m_pObserver) m_pObserver->OnStateChanged(READING_MUSIC_INFO); } } return songsToAdd.size(); }
bool CGUIWindowPrograms::GetDirectory(const CStdString &strDirectory, CFileItemList &items) { #ifdef __APPLE__ // Launch Mac OS X apps if (Cocoa_IsAppBundle(strDirectory.c_str())) { if (strDirectory.Find("/Front Row.app/") > 0) { PlexRemoteHelper::Get().Stop(); Cocoa_LaunchFrontRow(); return true; } else { // Special cases for app compatibility if ((strDirectory.Find("/DVD Player.app/") > 0) || (strDirectory.Find("/iTunes.app/") > 0) || (strDirectory.Find("/EyeTV.app/") > 0)) PlexRemoteHelper::Get().Stop(); Cocoa_LaunchApp(strDirectory.c_str()); return true; } } // Launch Automator workflows if (Cocoa_IsWflowBundle(strDirectory.c_str())) { PlexRemoteHelper::Get().Stop(); Cocoa_LaunchAutomatorWorkflow(strDirectory.c_str()); return true; } #endif bool bFlattened=false; if (CUtil::IsDVD(strDirectory)) { CStdString strPath; CUtil::AddFileToFolder(strDirectory,"default.xbe",strPath); if (CFile::Exists(strPath)) // flatten dvd { CFileItemPtr item(new CFileItem("default.xbe")); item->m_strPath = strPath; items.Add(item); items.m_strPath=strDirectory; bFlattened = true; } } if (!bFlattened) if (!CGUIMediaWindow::GetDirectory(strDirectory, items)) return false; if (items.IsVirtualDirectoryRoot()) { // Set thumbnail images for OS X apps & workflows added as sources for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; if (item->m_strPath.Find(".app/") > 0) { //Get the app's icon CStdString appIcon = Cocoa_GetAppIcon(item->m_strPath.c_str()); if (appIcon != NULL) item->SetThumbnailImage(appIcon); } if (item->m_strPath.Find(".workflow/") > 0) item->SetThumbnailImage(Cocoa_GetIconFromBundle("/Applications/Automator.app", "AutomatorDocument")); } return true; } // flatten any folders m_database.BeginTransaction(); DWORD dwTick=timeGetTime(); bool bProgressVisible = false; for (int i = 0; i < items.Size(); i++) { CStdString shortcutPath; CFileItemPtr item = items[i]; if (!bProgressVisible && timeGetTime()-dwTick>1500 && m_dlgProgress) { // tag loading takes more then 1.5 secs, show a progress dialog m_dlgProgress->SetHeading(189); m_dlgProgress->SetLine(0, 20120); m_dlgProgress->SetLine(1,""); m_dlgProgress->SetLine(2, item->GetLabel()); m_dlgProgress->StartModal(); bProgressVisible = true; } if (bProgressVisible) { m_dlgProgress->SetLine(2,item->GetLabel()); m_dlgProgress->Progress(); } if (item->m_bIsFolder && !item->IsParentFolder()) { // folder item - let's check for a default.xbe file, and flatten if we have one CStdString defaultXBE; CUtil::AddFileToFolder(item->m_strPath, "default.xbe", defaultXBE); if (CFile::Exists(defaultXBE)) { // yes, format the item up item->m_strPath = defaultXBE; item->m_bIsFolder = false; } } else if (item->IsShortCut()) { // resolve the shortcut to set it's description etc. // and save the old shortcut path (so we can reassign it later) CShortcut cut; if (cut.Create(item->m_strPath)) { shortcutPath = item->m_strPath; item->m_strPath = cut.m_strPath; item->SetThumbnailImage(cut.m_strThumb); LABEL_MASKS labelMasks; m_guiState->GetSortMethodLabelMasks(labelMasks); CLabelFormatter formatter("", labelMasks.m_strLabel2File); if (!cut.m_strLabel.IsEmpty()) { item->SetLabel(cut.m_strLabel); struct __stat64 stat; if (CFile::Stat(item->m_strPath,&stat) == 0) item->m_dwSize = stat.st_size; formatter.FormatLabel2(item.get()); item->SetLabelPreformated(true); } } } if (!shortcutPath.IsEmpty()) item->m_strPath = shortcutPath; // Special case for OS X application bundles if (item->GetLabel().Find(".app") > 0) { //Remove .app from the end of the label CStdString itemLabel = item->GetLabel(); CUtil::RemoveExtension(itemLabel); item->SetLabel(itemLabel); //Get the app's icon CStdString appIcon = Cocoa_GetAppIcon(item->m_strPath.c_str()); if (appIcon != NULL) item->SetThumbnailImage(appIcon); } // Special case for Automator workflows if (item->GetLabel().Find(".workflow") > 0) { CStdString itemLabel = item->GetLabel(); CUtil::RemoveExtension(itemLabel); item->SetLabel(itemLabel); item->SetThumbnailImage(Cocoa_GetIconFromBundle("/Applications/Automator.app", "AutomatorDocument")); } } m_database.CommitTransaction(); // set the cached thumbs items.SetThumbnailImage(""); items.SetCachedProgramThumbs(); items.SetCachedProgramThumb(); if (!items.HasThumbnail()) items.SetUserProgramThumb(); if (bProgressVisible) m_dlgProgress->Close(); return true; }