Merge pull request #3020 from brooc/master
[vuplus_xbmc] / xbmc / music / MusicThumbLoader.cpp
1 /*
2  *      Copyright (C) 2012-2013 Team XBMC
3  *      http://xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 #include "MusicThumbLoader.h"
22 #include "FileItem.h"
23 #include "TextureCache.h"
24 #include "music/tags/MusicInfoTag.h"
25 #include "music/tags/MusicInfoTagLoaderFactory.h"
26 #include "music/infoscanner/MusicInfoScanner.h"
27 #include "music/Artist.h"
28 #include "video/VideoThumbLoader.h"
29
30 using namespace std;
31 using namespace MUSIC_INFO;
32
33 CMusicThumbLoader::CMusicThumbLoader() : CThumbLoader()
34 {
35   m_musicDatabase = new CMusicDatabase;
36 }
37
38 CMusicThumbLoader::~CMusicThumbLoader()
39 {
40   delete m_musicDatabase;
41 }
42
43 void CMusicThumbLoader::OnLoaderStart()
44 {
45   m_musicDatabase->Open();
46   m_albumArt.clear();
47   CThumbLoader::OnLoaderStart();
48 }
49
50 void CMusicThumbLoader::OnLoaderFinish()
51 {
52   m_musicDatabase->Close();
53   m_albumArt.clear();
54   CThumbLoader::OnLoaderFinish();
55 }
56
57 bool CMusicThumbLoader::LoadItem(CFileItem* pItem)
58 {
59   bool result  = LoadItemCached(pItem);
60        result |= LoadItemLookup(pItem);
61
62   return result;
63 }
64
65 bool CMusicThumbLoader::LoadItemCached(CFileItem* pItem)
66 {
67   if (pItem->m_bIsShareOrDrive)
68     return false;
69
70   if (pItem->HasMusicInfoTag() && pItem->GetArt().empty())
71   {
72     if (FillLibraryArt(*pItem))
73       return true;
74       
75     if (pItem->GetMusicInfoTag()->GetType() == "artist")
76       return false; // No fallback
77   }
78
79   if (pItem->HasVideoInfoTag() && pItem->GetArt().empty())
80   { // music video
81     CVideoThumbLoader loader;
82     if (loader.LoadItemCached(pItem))
83       return true;
84   }
85
86   if (!pItem->HasArt("thumb"))
87   {
88     std::string art = GetCachedImage(*pItem, "thumb");
89     if (!art.empty())
90       pItem->SetArt("thumb", art);
91   }
92
93   if (!pItem->HasArt("fanart"))
94   {
95     std::string art = GetCachedImage(*pItem, "fanart");
96     if (!art.empty())
97     {
98       pItem->SetArt("fanart", art);
99     }
100     else if (pItem->HasMusicInfoTag() && !pItem->GetMusicInfoTag()->GetArtist().empty())
101     {
102       std::string artist = pItem->GetMusicInfoTag()->GetArtist()[0];
103       m_musicDatabase->Open();
104       int idArtist = m_musicDatabase->GetArtistByName(artist);
105       if (idArtist >= 0)
106       {
107         string fanart = m_musicDatabase->GetArtForItem(idArtist, "artist", "fanart");
108         if (!fanart.empty())
109         {
110           pItem->SetArt("artist.fanart", fanart);
111           pItem->SetArtFallback("fanart", "artist.fanart");
112         }
113       }
114       m_musicDatabase->Close();
115     }
116   }
117
118   return false;
119 }
120
121 bool CMusicThumbLoader::LoadItemLookup(CFileItem* pItem)
122 {
123   if (pItem->m_bIsShareOrDrive)
124     return false;
125
126   if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->GetType() == "artist") // No fallback for artist
127     return false;
128
129   if (pItem->HasVideoInfoTag())
130   { // music video
131     CVideoThumbLoader loader;
132     if (loader.LoadItemLookup(pItem))
133       return true;
134   }
135
136   if (!pItem->HasArt("thumb"))
137   {
138     // Look for embedded art
139     if (pItem->HasMusicInfoTag() && !pItem->GetMusicInfoTag()->GetCoverArtInfo().empty())
140     {
141       // The item has got embedded art but user thumbs overrule, so check for those first
142       if (!FillThumb(*pItem, false)) // Check for user thumbs but ignore folder thumbs
143       {
144         // No user thumb, use embedded art
145         CStdString thumb = CTextureCache::GetWrappedImageURL(pItem->GetPath(), "music");
146         pItem->SetArt("thumb", thumb);
147       }
148     }
149     else
150     {
151       // Check for user thumbs
152       FillThumb(*pItem, true);
153     }
154   }
155
156   return true;
157 }
158
159 bool CMusicThumbLoader::FillThumb(CFileItem &item, bool folderThumbs /* = true */)
160 {
161   if (item.HasArt("thumb"))
162     return true;
163   CStdString thumb = GetCachedImage(item, "thumb");
164   if (thumb.IsEmpty())
165   {
166     thumb = item.GetUserMusicThumb(false, folderThumbs);
167     if (!thumb.IsEmpty())
168       SetCachedImage(item, "thumb", thumb);
169   }
170   item.SetArt("thumb", thumb);
171   return !thumb.IsEmpty();
172 }
173
174 bool CMusicThumbLoader::FillLibraryArt(CFileItem &item)
175 {
176   CMusicInfoTag &tag = *item.GetMusicInfoTag();
177   if (tag.GetDatabaseId() > -1 && !tag.GetType().empty())
178   {
179     m_musicDatabase->Open();
180     map<string, string> artwork;
181     if (m_musicDatabase->GetArtForItem(tag.GetDatabaseId(), tag.GetType(), artwork))
182       item.SetArt(artwork);
183     else if (tag.GetType() == "song")
184     { // no art for the song, try the album
185       ArtCache::const_iterator i = m_albumArt.find(tag.GetAlbumId());
186       if (i == m_albumArt.end())
187       {
188         m_musicDatabase->GetArtForItem(tag.GetAlbumId(), "album", artwork);
189         i = m_albumArt.insert(make_pair(tag.GetAlbumId(), artwork)).first;
190       }
191       if (i != m_albumArt.end())
192       {
193         item.AppendArt(i->second, "album");
194         for (map<string, string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
195           item.SetArtFallback(j->first, "album." + j->first);
196       }
197     }
198     if (tag.GetType() == "song" || tag.GetType() == "album")
199     { // fanart from the artist
200       string fanart = m_musicDatabase->GetArtistArtForItem(tag.GetDatabaseId(), tag.GetType(), "fanart");
201       if (!fanart.empty())
202       {
203         item.SetArt("artist.fanart", fanart);
204         item.SetArtFallback("fanart", "artist.fanart");
205       }
206     }
207     m_musicDatabase->Close();
208   }
209   return !item.GetArt().empty();
210 }
211
212 bool CMusicThumbLoader::GetEmbeddedThumb(const std::string &path, EmbeddedArt &art)
213 {
214   auto_ptr<IMusicInfoTagLoader> pLoader (CMusicInfoTagLoaderFactory::CreateLoader(path));
215   CMusicInfoTag tag;
216   if (NULL != pLoader.get())
217     pLoader->Load(path, tag, &art);
218
219   return !art.empty();
220 }