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 "GUIDialogMusicInfo.h"
22 #include "guilib/GUIWindowManager.h"
23 #include "guilib/GUIImage.h"
24 #include "dialogs/GUIDialogFileBrowser.h"
25 #include "GUIPassword.h"
26 #include "music/MusicDatabase.h"
27 #include "music/tags/MusicInfoTag.h"
29 #include "filesystem/File.h"
31 #include "profiles/ProfilesManager.h"
32 #include "storage/MediaManager.h"
33 #include "utils/AsyncFileCopy.h"
34 #include "settings/AdvancedSettings.h"
35 #include "settings/MediaSourceSettings.h"
36 #include "settings/Settings.h"
37 #include "guilib/Key.h"
38 #include "guilib/LocalizeStrings.h"
39 #include "utils/log.h"
40 #include "utils/URIUtils.h"
41 #include "utils/StringUtils.h"
42 #include "TextureCache.h"
43 #include "music/MusicThumbLoader.h"
44 #include "filesystem/Directory.h"
47 using namespace XFILE;
49 #define CONTROL_IMAGE 3
50 #define CONTROL_TEXTAREA 4
52 #define CONTROL_BTN_TRACKS 5
53 #define CONTROL_BTN_REFRESH 6
54 #define CONTROL_BTN_GET_THUMB 10
55 #define CONTROL_BTN_GET_FANART 12
57 #define CONTROL_LIST 50
59 CGUIDialogMusicInfo::CGUIDialogMusicInfo(void)
60 : CGUIDialog(WINDOW_DIALOG_MUSIC_INFO, "DialogAlbumInfo.xml")
61 , m_albumItem(new CFileItem)
64 m_albumSongs = new CFileItemList;
65 m_loadType = KEEP_IN_MEMORY;
68 CGUIDialogMusicInfo::~CGUIDialogMusicInfo(void)
73 bool CGUIDialogMusicInfo::OnMessage(CGUIMessage& message)
75 switch ( message.GetMessage() )
77 case GUI_MSG_WINDOW_DEINIT:
79 CGUIMessage message(GUI_MSG_LABEL_RESET, GetID(), CONTROL_LIST);
81 m_albumSongs->Clear();
85 case GUI_MSG_WINDOW_INIT:
87 CGUIDialog::OnMessage(message);
98 int iControl = message.GetSenderId();
99 if (iControl == CONTROL_BTN_REFRESH)
105 else if (iControl == CONTROL_BTN_GET_THUMB)
109 else if (iControl == CONTROL_BTN_TRACKS)
111 m_bViewReview = !m_bViewReview;
114 else if (iControl == CONTROL_LIST)
116 int iAction = message.GetParam1();
117 if (m_bArtistInfo && (ACTION_SELECT_ITEM == iAction || ACTION_MOUSE_LEFT_CLICK == iAction))
119 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControl);
120 g_windowManager.SendMessage(msg);
121 int iItem = msg.GetParam1();
122 if (iItem < 0 || iItem >= (int)m_albumSongs->Size())
124 CFileItemPtr item = m_albumSongs->Get(iItem);
125 OnSearch(item.get());
129 else if (iControl == CONTROL_BTN_GET_FANART)
137 return CGUIDialog::OnMessage(message);
140 bool CGUIDialogMusicInfo::OnAction(const CAction &action)
142 if (action.GetID() == ACTION_SHOW_INFO)
147 return CGUIDialog::OnAction(action);
150 void CGUIDialogMusicInfo::SetAlbum(const CAlbum& album, const CStdString &path)
153 SetSongs(m_album.songs);
154 *m_albumItem = CFileItem(path, true);
155 m_albumItem->GetMusicInfoTag()->SetAlbum(m_album.strAlbum);
156 m_albumItem->GetMusicInfoTag()->SetAlbumArtist(StringUtils::Join(m_album.artist, g_advancedSettings.m_musicItemSeparator));
157 m_albumItem->GetMusicInfoTag()->SetArtist(m_album.artist);
158 m_albumItem->GetMusicInfoTag()->SetYear(m_album.iYear);
159 m_albumItem->GetMusicInfoTag()->SetLoaded(true);
160 m_albumItem->GetMusicInfoTag()->SetRating('0' + m_album.iRating);
161 m_albumItem->GetMusicInfoTag()->SetGenre(m_album.genre);
162 m_albumItem->GetMusicInfoTag()->SetDatabaseId(m_album.idAlbum, "album");
163 CMusicDatabase::SetPropertiesFromAlbum(*m_albumItem,m_album);
165 CMusicThumbLoader loader;
166 loader.LoadItem(m_albumItem.get());
168 // set the artist thumb, fanart
169 if (!m_album.artist.empty())
173 map<string, string> artwork;
174 if (db.GetArtistArtForItem(m_album.idAlbum, "album", artwork))
176 if (artwork.find("thumb") != artwork.end())
177 m_albumItem->SetProperty("artistthumb", artwork["thumb"]);
178 if (artwork.find("fanart") != artwork.end())
179 m_albumItem->SetArt("fanart",artwork["fanart"]);
182 m_hasUpdatedThumb = false;
183 m_bArtistInfo = false;
184 m_albumSongs->SetContent("albums");
187 void CGUIDialogMusicInfo::SetArtist(const CArtist& artist, const CStdString &path)
191 *m_albumItem = CFileItem(path, true);
192 m_albumItem->SetLabel(artist.strArtist);
193 m_albumItem->GetMusicInfoTag()->SetAlbumArtist(m_artist.strArtist);
194 m_albumItem->GetMusicInfoTag()->SetArtist(m_artist.strArtist);
195 m_albumItem->GetMusicInfoTag()->SetLoaded(true);
196 m_albumItem->GetMusicInfoTag()->SetGenre(m_artist.genre);
197 m_albumItem->GetMusicInfoTag()->SetDatabaseId(m_artist.idArtist, "artist");
198 CMusicDatabase::SetPropertiesFromArtist(*m_albumItem,m_artist);
200 CMusicThumbLoader loader;
201 loader.LoadItem(m_albumItem.get());
203 m_hasUpdatedThumb = false;
204 m_bArtistInfo = true;
205 m_albumSongs->SetContent("artists");
208 void CGUIDialogMusicInfo::SetSongs(const VECSONGS &songs)
210 m_albumSongs->Clear();
211 for (unsigned int i = 0; i < songs.size(); i++)
213 const CSong& song = songs[i];
214 CFileItemPtr item(new CFileItem(song));
215 m_albumSongs->Add(item);
219 void CGUIDialogMusicInfo::SetDiscography()
221 m_albumSongs->Clear();
222 CMusicDatabase database;
225 for (unsigned int i=0;i<m_artist.discography.size();++i)
227 CFileItemPtr item(new CFileItem(m_artist.discography[i].first));
228 item->SetLabel2(m_artist.discography[i].second);
229 long idAlbum = database.GetAlbumByName(item->GetLabel(),m_artist.strArtist);
231 if (idAlbum != -1) // we need this slight stupidity to get correct case for the album name
232 item->SetArt("thumb", database.GetArtForItem(idAlbum, "album", "thumb"));
234 item->SetArt("thumb", "DefaultAlbumCover.png");
236 m_albumSongs->Add(item);
240 void CGUIDialogMusicInfo::Update()
244 CONTROL_ENABLE(CONTROL_BTN_GET_FANART);
246 SetLabel(CONTROL_TEXTAREA, m_artist.strBiography);
247 CGUIMessage message(GUI_MSG_LABEL_BIND, GetID(), CONTROL_LIST, 0, 0, m_albumSongs);
250 if (GetControl(CONTROL_BTN_TRACKS)) // if no CONTROL_BTN_TRACKS found - allow skinner full visibility control over CONTROL_TEXTAREA and CONTROL_LIST
254 SET_CONTROL_VISIBLE(CONTROL_TEXTAREA);
255 SET_CONTROL_HIDDEN(CONTROL_LIST);
256 SET_CONTROL_LABEL(CONTROL_BTN_TRACKS, 21888);
260 SET_CONTROL_VISIBLE(CONTROL_LIST);
261 SET_CONTROL_HIDDEN(CONTROL_TEXTAREA);
262 SET_CONTROL_LABEL(CONTROL_BTN_TRACKS, 21887);
268 CONTROL_DISABLE(CONTROL_BTN_GET_FANART);
270 SetLabel(CONTROL_TEXTAREA, m_album.strReview);
271 CGUIMessage message(GUI_MSG_LABEL_BIND, GetID(), CONTROL_LIST, 0, 0, m_albumSongs);
274 if (GetControl(CONTROL_BTN_TRACKS)) // if no CONTROL_BTN_TRACKS found - allow skinner full visibility control over CONTROL_TEXTAREA and CONTROL_LIST
278 SET_CONTROL_VISIBLE(CONTROL_TEXTAREA);
279 SET_CONTROL_HIDDEN(CONTROL_LIST);
280 SET_CONTROL_LABEL(CONTROL_BTN_TRACKS, 182);
284 SET_CONTROL_VISIBLE(CONTROL_LIST);
285 SET_CONTROL_HIDDEN(CONTROL_TEXTAREA);
286 SET_CONTROL_LABEL(CONTROL_BTN_TRACKS, 183);
290 // update the thumbnail
291 const CGUIControl* pControl = GetControl(CONTROL_IMAGE);
294 CGUIImage* pImageControl = (CGUIImage*)pControl;
295 pImageControl->FreeResources();
296 pImageControl->SetFileName(m_albumItem->GetArt("thumb"));
299 // disable the GetThumb button if the user isn't allowed it
300 CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_GET_THUMB, CProfilesManager::Get().GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser);
303 void CGUIDialogMusicInfo::SetLabel(int iControl, const CStdString& strLabel)
305 if (strLabel.IsEmpty())
307 SET_CONTROL_LABEL(iControl, (iControl == CONTROL_TEXTAREA) ? (m_bArtistInfo?547:414) : 416);
311 SET_CONTROL_LABEL(iControl, strLabel);
315 bool CGUIDialogMusicInfo::NeedRefresh() const
320 void CGUIDialogMusicInfo::OnInitWindow()
322 CGUIDialog::OnInitWindow();
325 // Get Thumb from user choice.
328 // 2. AllMusic.com thumb
330 // 4. No thumb (if no Local thumb is available)
332 // TODO: Currently no support for "embedded thumb" as there is no easy way to grab it
333 // without sending a file that has this as it's album to this class
334 void CGUIDialogMusicInfo::OnGetThumb()
339 if (CFile::Exists(m_albumItem->GetArt("thumb")))
341 CFileItemPtr item(new CFileItem("thumb://Current", false));
342 item->SetArt("thumb", m_albumItem->GetArt("thumb"));
343 item->SetLabel(g_localizeStrings.Get(20016));
347 // Grab the thumbnail(s) from the web
348 vector<CStdString> thumbs;
350 m_artist.thumbURL.GetThumbURLs(thumbs);
352 m_album.thumbURL.GetThumbURLs(thumbs);
354 for (unsigned int i = 0; i < thumbs.size(); ++i)
356 CStdString strItemPath;
357 strItemPath = StringUtils::Format("thumb://Remote%i", i);
358 CFileItemPtr item(new CFileItem(strItemPath, false));
359 item->SetArt("thumb", thumbs[i]);
360 item->SetIconImage("DefaultPicture.png");
361 item->SetLabel(g_localizeStrings.Get(20015));
363 // TODO: Do we need to clear the cached image?
364 // CTextureCache::Get().ClearCachedImage(thumb);
369 CStdString localThumb;
372 CMusicDatabase database;
374 CStdString strArtistPath;
375 if (database.GetArtistPath(m_artist.idArtist,strArtistPath))
376 localThumb = URIUtils::AddFileToFolder(strArtistPath, "folder.jpg");
379 localThumb = m_albumItem->GetUserMusicThumb();
380 if (CFile::Exists(localThumb))
382 CFileItemPtr item(new CFileItem("thumb://Local", false));
383 item->SetArt("thumb", localThumb);
384 item->SetLabel(g_localizeStrings.Get(20017));
389 CFileItemPtr item(new CFileItem("thumb://None", false));
391 item->SetIconImage("DefaultArtist.png");
393 item->SetIconImage("DefaultAlbumCover.png");
394 item->SetLabel(g_localizeStrings.Get(20018));
400 VECSOURCES sources(*CMediaSourceSettings::Get().GetSources("music"));
401 AddItemPathToFileBrowserSources(sources, *m_albumItem);
402 g_mediaManager.GetLocalDrives(sources);
403 if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(1030), result, &flip))
404 return; // user cancelled
406 if (result == "thumb://Current")
407 return; // user chose the one they have
410 if (result.Left(14) == "thumb://Remote")
412 int number = atoi(result.Mid(14));
413 newThumb = thumbs[number];
415 else if (result == "thumb://Local")
416 newThumb = localThumb;
417 else if (CFile::Exists(result))
420 newThumb = "-"; // force local thumbs to be ignored
422 // update thumb in the database
426 db.SetArtForItem(m_albumItem->GetMusicInfoTag()->GetDatabaseId(), m_albumItem->GetMusicInfoTag()->GetType(), "thumb", newThumb);
430 m_albumItem->SetArt("thumb", newThumb);
431 m_hasUpdatedThumb = true;
433 // tell our GUI to completely reload all controls (as some of them
434 // are likely to have had this image in use so will need refreshing)
435 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
436 g_windowManager.SendMessage(msg);
442 // Allow user to select a Fanart
443 void CGUIDialogMusicInfo::OnGetFanart()
447 if (m_albumItem->HasArt("fanart"))
449 CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false));
450 itemCurrent->SetArt("thumb", m_albumItem->GetArt("fanart"));
451 itemCurrent->SetLabel(g_localizeStrings.Get(20440));
452 items.Add(itemCurrent);
455 // Grab the thumbnails from the web
456 for (unsigned int i = 0; i < m_artist.fanart.GetNumFanarts(); i++)
458 CStdString strItemPath = StringUtils::Format("fanart://Remote%i",i);
459 CFileItemPtr item(new CFileItem(strItemPath, false));
460 CStdString thumb = m_artist.fanart.GetPreviewURL(i);
461 item->SetArt("thumb", CTextureUtils::GetWrappedThumbURL(thumb));
462 item->SetIconImage("DefaultPicture.png");
463 item->SetLabel(g_localizeStrings.Get(20441));
465 // TODO: Do we need to clear the cached image?
466 // CTextureCache::Get().ClearCachedImage(thumb);
470 // Grab a local thumb
471 CMusicDatabase database;
473 CStdString strArtistPath;
474 database.GetArtistPath(m_artist.idArtist,strArtistPath);
475 CFileItem item(strArtistPath,true);
476 CStdString strLocal = item.GetLocalFanart();
477 if (!strLocal.IsEmpty())
479 CFileItemPtr itemLocal(new CFileItem("fanart://Local",false));
480 itemLocal->SetArt("thumb", strLocal);
481 itemLocal->SetLabel(g_localizeStrings.Get(20438));
483 // TODO: Do we need to clear the cached image?
484 CTextureCache::Get().ClearCachedImage(strLocal);
485 items.Add(itemLocal);
489 CFileItemPtr itemNone(new CFileItem("fanart://None", false));
490 itemNone->SetIconImage("DefaultArtist.png");
491 itemNone->SetLabel(g_localizeStrings.Get(20439));
496 VECSOURCES sources = *CMediaSourceSettings::Get().GetSources("music");
497 g_mediaManager.GetLocalDrives(sources);
499 if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445))
500 return; // user cancelled
502 // delete the thumbnail if that's what the user wants, else overwrite with the
504 if (result.Equals("fanart://Current"))
507 if (result.Equals("fanart://Local"))
510 if (result.Left(15) == "fanart://Remote")
512 int iFanart = atoi(result.Mid(15).c_str());
513 m_artist.fanart.SetPrimaryFanart(iFanart);
514 result = m_artist.fanart.GetImageURL();
516 else if (result.Equals("fanart://None") || !CFile::Exists(result))
519 if (flip && !result.empty())
520 result = CTextureUtils::GetWrappedImageURL(result, "", "flipped");
522 // update thumb in the database
526 db.SetArtForItem(m_albumItem->GetMusicInfoTag()->GetDatabaseId(), m_albumItem->GetMusicInfoTag()->GetType(), "fanart", result);
530 m_albumItem->SetArt("fanart", result);
531 m_hasUpdatedThumb = true;
532 // tell our GUI to completely reload all controls (as some of them
533 // are likely to have had this image in use so will need refreshing)
534 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
535 g_windowManager.SendMessage(msg);
540 void CGUIDialogMusicInfo::OnSearch(const CFileItem* pItem)
542 CMusicDatabase database;
544 long idAlbum = database.GetAlbumByName(pItem->GetLabel(),m_artist.strArtist);
548 if (database.GetAlbumInfo(idAlbum,album,&album.songs))
551 database.GetAlbumPath(idAlbum,strPath);
552 SetAlbum(album,strPath);
558 CFileItemPtr CGUIDialogMusicInfo::GetCurrentListItem(int offset)
563 void CGUIDialogMusicInfo::AddItemPathToFileBrowserSources(VECSOURCES &sources, const CFileItem &item)
567 if (item.HasMusicInfoTag() && item.GetMusicInfoTag()->GetType() == "song")
568 itemDir = URIUtils::GetParentPath(item.GetMusicInfoTag()->GetURL());
570 itemDir = item.GetPath();
572 if (!itemDir.IsEmpty() && CDirectory::Exists(itemDir))
574 CMediaSource itemSource;
575 itemSource.strName = g_localizeStrings.Get(36041);
576 itemSource.strPath = itemDir;
577 sources.push_back(itemSource);