2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "MusicInfoLoader.h"
22 #include "MusicDatabase.h"
23 #include "music/infoscanner/MusicInfoScanner.h"
24 #include "music/tags/MusicInfoTagLoaderFactory.h"
25 #include "filesystem/DirectoryCache.h"
26 #include "filesystem/MusicDatabaseDirectory.h"
27 #include "filesystem/MusicDatabaseDirectory/DirectoryNode.h"
28 #include "filesystem/MusicDatabaseDirectory/QueryParams.h"
29 #include "utils/URIUtils.h"
30 #include "music/tags/MusicInfoTag.h"
31 #include "filesystem/File.h"
32 #include "settings/Settings.h"
34 #include "utils/log.h"
37 #include "MusicThumbLoader.h"
40 using namespace XFILE;
41 using namespace MUSIC_INFO;
43 // HACK until we make this threadable - specify 1 thread only for now
44 CMusicInfoLoader::CMusicInfoLoader() : CBackgroundInfoLoader()
46 m_mapFileItems = new CFileItemList;
48 m_thumbLoader = new CMusicThumbLoader();
51 CMusicInfoLoader::~CMusicInfoLoader()
54 delete m_mapFileItems;
58 void CMusicInfoLoader::OnLoaderStart()
60 // Load previously cached items from HD
61 if (!m_strCacheFileName.empty())
62 LoadCache(m_strCacheFileName, *m_mapFileItems);
65 m_mapFileItems->SetPath(m_pVecItems->GetPath());
66 m_mapFileItems->Load();
67 m_mapFileItems->SetFastLookup(true);
70 m_strPrevPath.clear();
72 m_databaseHits = m_tagReads = 0;
74 if (m_pProgressCallback)
75 m_pProgressCallback->SetProgressMax(m_pVecItems->GetFileCount());
77 m_musicDatabase.Open();
80 m_thumbLoader->OnLoaderStart();
83 bool CMusicInfoLoader::LoadAdditionalTagInfo(CFileItem* pItem)
85 if (!pItem || pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream())
88 if (pItem->GetProperty("hasfullmusictag") == "true")
89 return false; // already have the information
91 CStdString path(pItem->GetPath());
92 if (pItem->IsMusicDb())
94 // set the artist / album properties
95 XFILE::MUSICDATABASEDIRECTORY::CQueryParams param;
96 XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(pItem->GetPath(),param);
98 CMusicDatabase database;
100 if (database.GetArtist(param.GetArtistId(), artist, false))
101 CMusicDatabase::SetPropertiesFromArtist(*pItem,artist);
104 if (database.GetAlbum(param.GetAlbumId(), album, false))
105 CMusicDatabase::SetPropertiesFromAlbum(*pItem,album);
107 path = pItem->GetMusicInfoTag()->GetURL();
110 CLog::Log(LOGDEBUG, "Loading additional tag info for file %s", path.c_str());
112 // we load up the actual tag for this file
113 auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(path));
114 if (NULL != pLoader.get())
117 pLoader->Load(path, tag);
118 // then we set the fields from the file tags to the item
119 pItem->SetProperty("lyrics", tag.GetLyrics());
120 pItem->SetProperty("hasfullmusictag", "true");
126 bool CMusicInfoLoader::LoadItem(CFileItem* pItem)
128 bool result = LoadItemCached(pItem);
129 result |= LoadItemLookup(pItem);
134 bool CMusicInfoLoader::LoadItemCached(CFileItem* pItem)
136 if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream())
139 // Get thumb for item
140 m_thumbLoader->LoadItem(pItem);
145 bool CMusicInfoLoader::LoadItemLookup(CFileItem* pItem)
147 if (m_pProgressCallback && !pItem->m_bIsFolder)
148 m_pProgressCallback->SetProgressAdvance();
150 if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream())
153 if (!pItem->HasMusicInfoTag() || !pItem->GetMusicInfoTag()->Loaded())
155 // first check the cached item
156 CFileItemPtr mapItem = (*m_mapFileItems)[pItem->GetPath()];
157 if (mapItem && mapItem->m_dateTime==pItem->m_dateTime && mapItem->HasMusicInfoTag() && mapItem->GetMusicInfoTag()->Loaded())
158 { // Query map if we previously cached the file on HD
159 *pItem->GetMusicInfoTag() = *mapItem->GetMusicInfoTag();
160 if (mapItem->HasArt("thumb"))
161 pItem->SetArt("thumb", mapItem->GetArt("thumb"));
165 CStdString strPath = URIUtils::GetDirectory(pItem->GetPath());
166 URIUtils::AddSlashAtEnd(strPath);
167 if (strPath!=m_strPrevPath)
169 // The item is from another directory as the last one,
170 // query the database for the new directory...
171 m_musicDatabase.GetSongsByPath(strPath, m_songsMap);
175 MAPSONGS::iterator it = m_songsMap.find(pItem->GetPath());
176 if (it != m_songsMap.end())
177 { // Have we loaded this item from database before
178 pItem->GetMusicInfoTag()->SetSong(it->second);
179 if (!it->second.strThumb.empty())
180 pItem->SetArt("thumb", it->second.strThumb);
182 else if (pItem->IsMusicDb())
183 { // a music db item that doesn't have tag loaded - grab details from the database
184 XFILE::MUSICDATABASEDIRECTORY::CQueryParams param;
185 XFILE::MUSICDATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(pItem->GetPath(),param);
187 if (m_musicDatabase.GetSong(param.GetSongId(), song))
189 pItem->GetMusicInfoTag()->SetSong(song);
190 if (!song.strThumb.empty())
191 pItem->SetArt("thumb", song.strThumb);
194 else if (CSettings::Get().GetBool("musicfiles.usetags") || pItem->IsCDDA())
195 { // Nothing found, load tag from file,
196 // always try to load cddb info
197 // get correct tag parser
198 auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(pItem->GetPath()));
199 if (NULL != pLoader.get())
201 pLoader->Load(pItem->GetPath(), *pItem->GetMusicInfoTag());
205 m_strPrevPath = strPath;
212 void CMusicInfoLoader::OnLoaderFinish()
214 // cleanup last loaded songs from database
217 // cleanup cache loaded from HD
218 m_mapFileItems->Clear();
220 // Save loaded items to HD
221 if (!m_strCacheFileName.empty())
222 SaveCache(m_strCacheFileName, *m_pVecItems);
223 else if (!m_bStop && (m_databaseHits > 1 || m_tagReads > 0))
226 m_musicDatabase.Close();
229 m_thumbLoader->OnLoaderFinish();
232 void CMusicInfoLoader::UseCacheOnHD(const CStdString& strFileName)
234 m_strCacheFileName = strFileName;
237 void CMusicInfoLoader::LoadCache(const CStdString& strFileName, CFileItemList& items)
241 if (file.Open(strFileName))
243 CArchive ar(&file, CArchive::load);
246 for (int i = 0; i < iSize; i++)
248 CFileItemPtr pItem(new CFileItem());
254 items.SetFastLookup(true);
258 void CMusicInfoLoader::SaveCache(const CStdString& strFileName, CFileItemList& items)
260 int iSize = items.Size();
267 if (file.OpenForWrite(strFileName))
269 CArchive ar(&file, CArchive::store);
270 ar << (int)items.Size();
271 for (int i = 0; i < iSize; i++)
273 CFileItemPtr pItem = items[i];