diff options
75 files changed, 892 insertions, 551 deletions
diff --git a/language/English/strings.po b/language/English/strings.po index 78e9dc0301..424dc943d1 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -4891,7 +4891,27 @@ msgctxt "#13510" msgid "Sync playback to display" msgstr "" -#empty strings from id 13511 to 13549 +msgctxt "#13511" +msgid "Choose art" +msgstr "" + +msgctxt "#13512" +msgid "Current art" +msgstr "" + +msgctxt "#13513" +msgid "Remote art" +msgstr "" + +msgctxt "#13514" +msgid "Local art" +msgstr "" + +msgctxt "#13515" +msgid "No art" +msgstr "" + +#empty strings from id 13516 to 13549 msgctxt "#13550" msgid "Pause during refresh rate change" diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 9f32e555be..b60aba2f2f 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -968,6 +968,12 @@ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">true</ExcludedFromBuild> </ClCompile> + <ClCompile Include="..\..\xbmc\test\TestFileItem.cpp"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release (DirectX)|Win32'">true</ExcludedFromBuild> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release (OpenGL)|Win32'">true</ExcludedFromBuild> + </ClCompile> <ClCompile Include="..\..\xbmc\test\TestUtils.cpp"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug (DirectX)|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">true</ExcludedFromBuild> diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index b341508bce..5e784ba595 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -2936,6 +2936,9 @@ <ClCompile Include="..\..\xbmc\dialogs\GUIDialogMediaFilter.cpp"> <Filter>dialogs</Filter> </ClCompile> + <ClCompile Include="..\..\xbmc\test\TestFileItem.cpp"> + <Filter>test</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\xbmc\win32\pch.h"> diff --git a/xbmc/AutoSwitch.cpp b/xbmc/AutoSwitch.cpp index b8071b573c..f32de1f138 100644 --- a/xbmc/AutoSwitch.cpp +++ b/xbmc/AutoSwitch.cpp @@ -125,7 +125,7 @@ bool CAutoSwitch::ByFolders(const CFileItemList& vecItems) for (int i = 0; i < vecItems.Size(); i++) { const CFileItemPtr pItem = vecItems[i]; - if (pItem->HasThumbnail()) + if (pItem->HasArt("thumb")) { bThumbs = true; break; @@ -156,7 +156,7 @@ bool CAutoSwitch::ByFiles(bool bHideParentDirItems, const CFileItemList& vecItem for (int i = 0; i < vecItems.Size(); i++) { const CFileItemPtr pItem = vecItems[i]; - if (pItem->HasThumbnail()) + if (pItem->HasArt("thumb")) { bThumbs = true; break; @@ -185,7 +185,7 @@ bool CAutoSwitch::ByThumbPercent(bool bHideParentDirItems, int iPercent, const C for (int i = 0; i < vecItems.Size(); i++) { const CFileItemPtr pItem = vecItems[i]; - if (pItem->HasThumbnail()) + if (pItem->HasArt("thumb")) { iNumThumbs++; float fTempPercent = ( (float)iNumThumbs / (float)iNumItems ) * (float)100; @@ -226,7 +226,7 @@ bool CAutoSwitch::ByFolderThumbPercentage(bool hideParentDirItems, int percent, for (int i = 0; i < vecItems.Size(); i++) { const CFileItemPtr item = vecItems[i]; - if (item->m_bIsFolder && item->HasThumbnail()) + if (item->m_bIsFolder && item->HasArt("thumb")) { numThumbs++; if (numThumbs >= 0.01f * percent * (numItems - fileCount)) diff --git a/xbmc/Favourites.cpp b/xbmc/Favourites.cpp index 1a981571e4..f821ac425a 100644 --- a/xbmc/Favourites.cpp +++ b/xbmc/Favourites.cpp @@ -78,7 +78,7 @@ bool CFavourites::LoadFavourites(CStdString& strPath, CFileItemList& items) { CFileItemPtr item(new CFileItem(name)); item->SetPath(favourite->FirstChild()->Value()); - if (thumb) item->SetThumbnailImage(thumb); + if (thumb) item->SetArt("thumb", thumb); items.Add(item); } } @@ -100,8 +100,8 @@ bool CFavourites::Save(const CFileItemList &items) const CFileItemPtr item = items[i]; TiXmlElement favNode("favourite"); favNode.SetAttribute("name", item->GetLabel().c_str()); - if (item->HasThumbnail()) - favNode.SetAttribute("thumb", item->GetThumbnailImage().c_str()); + if (item->HasArt("thumb")) + favNode.SetAttribute("thumb", item->GetArt("thumb").c_str()); TiXmlText execute(item->GetPath()); favNode.InsertEndChild(execute); rootNode->InsertEndChild(favNode); @@ -131,7 +131,7 @@ bool CFavourites::AddOrRemove(CFileItem *item, int contextWindow) CFileItemPtr favourite(new CFileItem(item->GetLabel())); if (item->GetLabel().IsEmpty()) favourite->SetLabel(CUtil::GetTitleFromPath(item->GetPath(), item->m_bIsFolder)); - favourite->SetThumbnailImage(item->GetThumbnailImage()); + favourite->SetArt("thumb", item->GetArt("thumb")); favourite->SetPath(executePath); items.Add(favourite); } diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index f36d1ce2a9..dabe92369d 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -82,7 +82,7 @@ CFileItem::CFileItem(const CSong& song) m_lStartPartNumber = 1; SetProperty("item_start", song.iStartOffset); m_lEndOffset = song.iEndOffset; - m_strThumbnailImage = song.strThumb; + SetArt("thumb", song.strThumb); } CFileItem::CFileItem(const CStdString &path, const CAlbum& album) @@ -169,10 +169,7 @@ CFileItem::CFileItem(const CEpgInfoTag& tag) m_dateTime = tag.StartAsLocalTime(); if (!tag.Icon().IsEmpty()) - { - SetThumbnailImage(tag.Icon()); SetIconImage(tag.Icon()); - } } CFileItem::CFileItem(const CPVRChannel& channel) @@ -217,10 +214,7 @@ CFileItem::CFileItem(const CPVRChannel& channel) } if (!channel.IconPath().IsEmpty()) - { - SetThumbnailImage(channel.IconPath()); SetIconImage(channel.IconPath()); - } SetProperty("channelid", channel.ChannelID()); SetProperty("path", channel.Path()); @@ -265,10 +259,7 @@ CFileItem::CFileItem(const CPVRTimerInfoTag& timer) m_dateTime = timer.StartAsLocalTime(); if (!timer.ChannelIcon().IsEmpty()) - { - SetThumbnailImage(timer.ChannelIcon()); SetIconImage(timer.ChannelIcon()); - } } CFileItem::CFileItem(const CArtist& artist) @@ -398,7 +389,7 @@ CFileItem::CFileItem(const CMediaSource& share) m_iHasLock = share.m_iHasLock; m_iBadPwdCount = share.m_iBadPwdCount; m_iDriveType = share.m_iDriveType; - m_strThumbnailImage = share.m_strThumbnailImage; + SetArt("thumb", share.m_strThumbnailImage); SetLabelPreformated(true); if (IsDVD()) GetVideoInfoTag()->m_strFileNameAndPath = share.strDiskUniqueId; // share.strDiskUniqueId contains disc unique id @@ -1472,8 +1463,8 @@ void CFileItem::UpdateInfo(const CFileItem &item, bool replaceLabels /*=true*/) SetLabel(item.GetLabel()); if (replaceLabels && !item.GetLabel2().IsEmpty()) SetLabel2(item.GetLabel2()); - if (!item.GetThumbnailImage().IsEmpty()) - SetThumbnailImage(item.GetThumbnailImage()); + if (!item.GetArt("thumb").empty()) + SetArt("thumb", item.GetArt("thumb")); if (!item.GetIconImage().IsEmpty()) SetIconImage(item.GetIconImage()); AppendProperties(item); @@ -2793,16 +2784,10 @@ CStdString CFileItem::GetTBNFile() const return thumbFile; } -CStdString CFileItem::GetUserVideoThumb() const +CStdString CFileItem::FindLocalArt(const std::string &artFile, bool useFolder) const { - if (IsTuxBox()) - { - if (!m_bIsFolder) - return g_tuxbox.GetPicon(GetLabel()); - else return ""; - } - - if (m_strPath.IsEmpty() + // ignore a bunch that are meaningless + if (m_strPath.empty() || m_bIsShareOrDrive || IsInternetStream() || URIUtils::IsUPnP(m_strPath) @@ -2814,46 +2799,71 @@ CStdString CFileItem::GetUserVideoThumb() const || IsDVD()) return ""; + CStdString thumb; + if (!m_bIsFolder) + { + thumb = GetLocalArt(artFile, false); + if (!thumb.empty() && CFile::Exists(thumb)) + return thumb; + } + if ((useFolder || (m_bIsFolder && !IsFileFolder())) && !artFile.empty()) + { + CStdString thumb2 = GetLocalArt(artFile, true); + if (!thumb2.empty() && thumb2 != thumb && CFile::Exists(thumb2)) + return thumb2; + } + return ""; +} - // 1. check <filename>.tbn or <foldername>.tbn - CStdString fileThumb(GetTBNFile()); - if (CFile::Exists(fileThumb)) - return fileThumb; +CStdString CFileItem::GetLocalArt(const std::string &artFile, bool useFolder) const +{ + // no retrieving of empty art files from folders + if (useFolder && artFile.empty()) + return ""; - if (IsOpticalMediaFile()) - { // special case for optical media "folders" - check the parent folder (or parent of parent) - // TODO: A better way to handle this would be to treat stacked folders as folders rather than files. - CFileItem item(GetLocalMetadataPath(), true); - CStdString thumb(item.GetUserVideoThumb()); - if (!thumb.IsEmpty()) - return thumb; + CStdString strFile = m_strPath; + if (IsStack()) + { +/* CFileItem item(CStackDirectory::GetFirstStackedFile(strFile),false); + CStdString localArt = item.GetLocalArt(artFile); + return localArt; + */ + CStdString strPath; + URIUtils::GetParentPath(m_strPath,strPath); + URIUtils::AddFileToFolder(strPath,URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(strFile)),strFile); } - // 2. - check movie.tbn, as long as it's not a folder - if (!m_bIsFolder) + if (URIUtils::IsInRAR(strFile) || URIUtils::IsInZIP(strFile)) { - CStdString strPath, movietbnFile; - URIUtils::GetParentPath(m_strPath, strPath); - URIUtils::AddFileToFolder(strPath, "movie.tbn", movietbnFile); - if (CFile::Exists(movietbnFile)) - return movietbnFile; + CStdString strPath, strParent; + URIUtils::GetDirectory(strFile,strPath); + URIUtils::GetParentPath(strPath,strParent); + URIUtils::AddFileToFolder(strParent,URIUtils::GetFileName(strFile),strFile); } - // 3. check folder image in_m_dvdThumbs (folder.jpg) - if (m_bIsFolder && !IsFileFolder()) + if (IsMultiPath()) + strFile = CMultiPathDirectory::GetFirstPath(m_strPath); + + if (IsOpticalMediaFile()) + { // optical media files should be treated like folders + useFolder = true; + strFile = GetLocalMetadataPath(); + } + else if (useFolder) + strFile = URIUtils::GetDirectory(strFile); + + if (strFile.empty()) // empty filepath -> nothing to find + return ""; + + if (useFolder) + return URIUtils::AddFileToFolder(strFile, artFile); + else { - CStdStringArray thumbs; - StringUtils::SplitString(g_advancedSettings.m_dvdThumbs, "|", thumbs); - for (unsigned int i = 0; i < thumbs.size(); ++i) - { - CStdString folderThumb(GetFolderThumb(thumbs[i])); - if (CFile::Exists(folderThumb)) - { - return folderThumb; - } - } + if (artFile.empty()) // old thumbnail matching + return URIUtils::ReplaceExtension(strFile, ".tbn"); + else + return URIUtils::ReplaceExtension(strFile, "-" + artFile); } - // No thumb found return ""; } @@ -2918,47 +2928,6 @@ CStdString CFileItem::GetBaseMoviePath(bool bUseFolderNames) const return strMovieName; } -#ifdef UNIT_TESTING -bool CFileItem::testGetBaseMoviePath() -{ - typedef struct - { - const char *file; - bool use_folder; - const char *base; - } testfiles; - - const testfiles test_files[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\filename.avi" }, - { "c:\\dir\\filename.avi", true, "c:\\dir\\" }, - { "/dir/filename.avi", false, "/dir/filename.avi" }, - { "/dir/filename.avi", true, "/dir/" }, - { "smb://somepath/file.avi", false, "smb://somepath/file.avi" }, - { "smb://somepath/file.avi", true, "smb://somepath/" }, - { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", false, "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi" }, - { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", true, "/path/to/movie_name/" }, - { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01.avi" }, - { "/home/user/TV Shows/Dexter/S1/1x01.avi", true, "/home/user/TV Shows/Dexter/S1/" }, - { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", true, "g:\\multimedia\\movies\\" }, - { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", false, "/home/user/movies/movie_name/" }, - { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", true, "/home/user/movies/movie_name/" }, - { "/home/user/movies/movie_name/BDMV/index.bdmv", false, "/home/user/movies/movie_name/" }, - { "/home/user/movies/movie_name/BDMV/index.bdmv", true, "/home/user/movies/movie_name/" }}; - - for (unsigned int i = 0; i < sizeof(test_files) / sizeof(testfiles); i++) - { - CFileItem item; - item.SetPath(test_files[i].file); - CStdString path = item.GetBaseMoviePath(test_files[i].use_folder); - if (path != test_files[i].base) - { - CLog::Log(LOGFATAL, "%s failed ('%s' -> '%s' != '%s')", __FUNCTION__, test_files[i].file, path.c_str(), test_files[i].base); - return false; - } - } - return true; -} -#endif - CStdString CFileItem::GetLocalFanart() const { if (IsVideoDb()) @@ -3012,7 +2981,7 @@ CStdString CFileItem::GetLocalFanart() const CFileItemList items; CDirectory::GetDirectory(strDir, items, g_settings.m_pictureExtensions, DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO); if (IsOpticalMediaFile()) - { // grab from the optical media parent folder as well - see GetUserVideoThumb + { // grab from the optical media parent folder as well CFileItemList moreItems; CDirectory::GetDirectory(GetLocalMetadataPath(), moreItems, g_settings.m_pictureExtensions, DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO); items.Append(moreItems); @@ -3075,7 +3044,7 @@ bool CFileItem::LoadMusicTag() if (musicDatabase.GetSongByFileName(m_strPath, song)) { GetMusicInfoTag()->SetSong(song); - SetThumbnailImage(song.strThumb); + SetArt("thumb", song.strThumb); return true; } musicDatabase.Close(); diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h index 3b023f2550..d3f83f00a3 100644 --- a/xbmc/FileItem.h +++ b/xbmc/FileItem.h @@ -272,6 +272,24 @@ public: */ CStdString GetLocalFanart() const; + /*! \brief Assemble the filename of a particular piece of local artwork for an item. + No file existence check is typically performed. + \param artFile the art file to search for. + \param useFolder whether to look in the folder for the art file. Defaults to false. + \return the path to the local artwork. + \sa FindLocalArt + */ + CStdString GetLocalArt(const std::string &artFile, bool useFolder = false) const; + + /*! \brief Assemble the filename of a particular piece of local artwork for an item, + and check for file existence. + \param artFile the art file to search for. + \param useFolder whether to look in the folder for the art file. Defaults to false. + \return the path to the local artwork if it exists, empty otherwise. + \sa GetLocalArt + */ + CStdString FindLocalArt(const std::string &artFile, bool useFolder) const; + // Gets the .tbn file associated with this item CStdString GetTBNFile() const; // Gets the folder image associated with this item (defaults to folder.jpg) @@ -288,12 +306,7 @@ public: */ CStdString GetBaseMoviePath(bool useFolderNames) const; -#ifdef UNIT_TESTING - static bool testGetBaseMoviePath(); -#endif - // Gets the user thumb, if it exists - CStdString GetUserVideoThumb() const; CStdString GetUserMusicThumb(bool alwaysCheckRemote = false) const; /*! \brief Get the path where we expect local metadata to reside. diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index 0c0649e069..b60e921752 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -199,7 +199,7 @@ const infomap player_labels[] = {{ "hasmedia", PLAYER_HAS_MEDIA }, { "pauseenabled", PLAYER_CAN_PAUSE }, { "seekenabled", PLAYER_CAN_SEEK }}; -const infomap player_param[] = {{ "property", PLAYER_ITEM_PROPERTY }}; +const infomap player_param[] = {{ "art", PLAYER_ITEM_ART }}; const infomap player_times[] = {{ "seektime", PLAYER_SEEKTIME }, { "seekoffset", PLAYER_SEEKOFFSET }, @@ -943,7 +943,11 @@ int CGUIInfoManager::TranslateSingleString(const CStdString &strCondition) return AddMultiInfo(GUIInfo(player_times[i].val, TranslateTimeFormat(prop.param()))); } if (prop.name == "property") + { + if (prop.param().Equals("fanart_image")) + return AddMultiInfo(GUIInfo(PLAYER_ITEM_ART, ConditionalStringParameter("fanart"))); return AddListItemProp(prop.param(), MUSICPLAYER_PROPERTY_OFFSET); + } return TranslateMusicPlayerString(prop.name); } else if (cat.name == "videoplayer") @@ -1181,7 +1185,13 @@ int CGUIInfoManager::TranslateListItem(const Property &info) return listitem_labels[i].val; } if (info.name == "property" && info.num_params() == 1) + { + if (info.param().Equals("fanart_image")) + return AddListItemProp("fanart", LISTITEM_ART_OFFSET); return AddListItemProp(info.param()); + } + if (info.name == "art" && info.num_params() == 1) + return AddListItemProp(info.param(), LISTITEM_ART_OFFSET); return 0; } @@ -1844,7 +1854,7 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow, CStdString *fa { CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW); if (window) - return ((CGUIMediaWindow *)window)->CurrentDirectory().GetProperty("fanart_image").asString(); + return ((CGUIMediaWindow *)window)->CurrentDirectory().GetArt("fanart"); } break; case SYSTEM_RENDER_VENDOR: @@ -2197,7 +2207,7 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI { CGUIWindow *pWindow = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW); if (pWindow) - bReturn = ((CGUIMediaWindow*)pWindow)->CurrentDirectory().HasThumbnail(); + bReturn = ((CGUIMediaWindow*)pWindow)->CurrentDirectory().HasArt("thumb"); } else if (condition == CONTAINER_HAS_NEXT || condition == CONTAINER_HAS_PREVIOUS || condition == CONTAINER_SCROLLING) { @@ -2964,9 +2974,9 @@ CStdString CGUIInfoManager::GetMultiInfoLabel(const GUIInfo &info, int contextWi if (m_seekOffset > 0) return "+" + seekOffset; } - else if (info.m_info == PLAYER_ITEM_PROPERTY) + else if (info.m_info == PLAYER_ITEM_ART) { - return m_currentFile->GetProperty(m_stringParameters[info.GetData1()]).asString(); + return m_currentFile->GetArt(m_stringParameters[info.GetData1()]); } else if (info.m_info == SYSTEM_TIME) { @@ -3093,7 +3103,7 @@ CStdString CGUIInfoManager::GetImage(int info, int contextWindow, CStdString *fa if (!g_application.IsPlayingAudio()) return ""; if (fallback) *fallback = "DefaultAlbumCover.png"; - return m_currentFile->HasThumbnail() ? m_currentFile->GetThumbnailImage() : "DefaultAlbumCover.png"; + return m_currentFile->HasArt("thumb") ? m_currentFile->GetArt("thumb") : "DefaultAlbumCover.png"; } else if (info == MUSICPLAYER_RATING) { @@ -3111,7 +3121,7 @@ CStdString CGUIInfoManager::GetImage(int info, int contextWindow, CStdString *fa if (fallback) *fallback = "DefaultVideoCover.png"; if(m_currentMovieThumb.IsEmpty()) - return m_currentFile->HasThumbnail() ? m_currentFile->GetThumbnailImage() : "DefaultVideoCover.png"; + return m_currentFile->HasArt("thumb") ? m_currentFile->GetArt("thumb") : "DefaultVideoCover.png"; else return m_currentMovieThumb; } else if (info == CONTAINER_FOLDERTHUMB) @@ -3124,13 +3134,13 @@ CStdString CGUIInfoManager::GetImage(int info, int contextWindow, CStdString *fa { CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW); if (window) - return ((CGUIMediaWindow *)window)->CurrentDirectory().GetProperty("tvshowthumb").asString(); + return ((CGUIMediaWindow *)window)->CurrentDirectory().GetArt("tvshowthumb"); } else if (info == CONTAINER_SEASONTHUMB) { CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW); if (window) - return ((CGUIMediaWindow *)window)->CurrentDirectory().GetProperty("seasonthumb").asString(); + return ((CGUIMediaWindow *)window)->CurrentDirectory().GetArt("seasonthumb"); } else if (info == LISTITEM_THUMB || info == LISTITEM_ICON || info == LISTITEM_ACTUAL_ICON || info == LISTITEM_OVERLAY || info == LISTITEM_RATING || info == LISTITEM_STAR_RATING) @@ -3348,12 +3358,12 @@ const CStdString CGUIInfoManager::GetMusicPlaylistInfo(const GUIInfo& info) playlistItem->GetMusicInfoTag()->SetLoaded(); } // try to set a thumbnail - if (!playlistItem->HasThumbnail()) + if (!playlistItem->HasArt("thumb")) { CMusicThumbLoader::FillThumb(*playlistItem); // still no thumb? then just the set the default cover TODO: remove me? - if (!playlistItem->HasThumbnail()) - playlistItem->SetThumbnailImage("DefaultAlbumCover.png"); + if (!playlistItem->HasArt("thumb")) + playlistItem->SetArt("thumb", "DefaultAlbumCover.png"); } if (info.m_info == MUSICPLAYER_PLAYLISTPOS) { @@ -3362,7 +3372,7 @@ const CStdString CGUIInfoManager::GetMusicPlaylistInfo(const GUIInfo& info) return strPosition; } else if (info.m_info == MUSICPLAYER_COVER) - return playlistItem->GetThumbnailImage(); + return playlistItem->GetArt("thumb"); return GetMusicTagLabel(info.m_info, playlistItem.get()); } @@ -3870,10 +3880,10 @@ void CGUIInfoManager::SetCurrentItem(CFileItem &item) void CGUIInfoManager::SetCurrentAlbumThumb(const CStdString thumbFileName) { if (CFile::Exists(thumbFileName)) - m_currentFile->SetThumbnailImage(thumbFileName); + m_currentFile->SetArt("thumb", thumbFileName); else { - m_currentFile->SetThumbnailImage(""); + m_currentFile->SetArt("thumb", ""); m_currentFile->FillInDefaultIcon(); } } @@ -3899,8 +3909,8 @@ void CGUIInfoManager::SetCurrentSong(CFileItem &item) CLog::Log(LOGDEBUG,"Streaming media detected... using %s to find a thumb", g_application.m_strPlayListFile.c_str()); CFileItem streamingItem(g_application.m_strPlayListFile,false); CMusicThumbLoader::FillThumb(streamingItem); - if (streamingItem.HasThumbnail()) - m_currentFile->SetThumbnailImage(streamingItem.GetThumbnailImage()); + if (streamingItem.HasArt("thumb")) + m_currentFile->SetArt("thumb", streamingItem.GetArt("thumb")); } } else @@ -3930,7 +3940,7 @@ void CGUIInfoManager::SetCurrentMovie(CFileItem &item) } // Find a thumb for this file. - if (!item.HasThumbnail()) + if (!item.HasArt("thumb")) { CVideoThumbLoader loader; loader.LoadItem(m_currentFile); @@ -3952,12 +3962,12 @@ void CGUIInfoManager::SetCurrentMovie(CFileItem &item) CLog::Log(LOGDEBUG,"Streaming media detected... using %s to find a thumb", g_application.m_strPlayListFile.c_str()); CFileItem thumbItem(g_application.m_strPlayListFile,false); if (CVideoThumbLoader::FillThumb(thumbItem)) - item.SetThumbnailImage(thumbItem.GetThumbnailImage()); + item.SetArt("thumb", thumbItem.GetArt("thumb")); } } item.FillInDefaultIcon(); - m_currentMovieThumb = item.GetThumbnailImage(); + m_currentMovieThumb = item.GetArt("thumb"); } string CGUIInfoManager::GetSystemHeatInfo(int info) @@ -4208,6 +4218,12 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, CStdSt if (info >= CONDITIONAL_LABEL_START && info <= CONDITIONAL_LABEL_END) return GetSkinVariableString(info, false, item); + if (info >= LISTITEM_PROPERTY_START + LISTITEM_ART_OFFSET && info - (LISTITEM_PROPERTY_START + LISTITEM_ART_OFFSET) < (int)m_listitemProperties.size()) + { // grab the art + std::string art = m_listitemProperties[info - (LISTITEM_PROPERTY_START + LISTITEM_ART_OFFSET)]; + return item->GetArt(art); + } + if (info >= LISTITEM_PROPERTY_START && info - LISTITEM_PROPERTY_START < (int)m_listitemProperties.size()) { // grab the property CStdString property = m_listitemProperties[info - LISTITEM_PROPERTY_START]; @@ -4519,7 +4535,7 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, CStdSt return item->GetIconImage(); case LISTITEM_ICON: { - CStdString strThumb = item->GetThumbnailImage(); + CStdString strThumb = item->GetArt("thumb"); if (strThumb.IsEmpty()) strThumb = item->GetIconImage(); if (fallback) @@ -4529,7 +4545,7 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, CStdSt case LISTITEM_OVERLAY: return item->GetOverlayImage(); case LISTITEM_THUMB: - return item->GetThumbnailImage(); + return item->GetArt("thumb"); case LISTITEM_FOLDERPATH: return CURL(item->GetPath()).GetWithoutUserDetails(); case LISTITEM_FOLDERNAME: diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h index 90d6bb27d0..6e34ce49ff 100644 --- a/xbmc/GUIInfoManager.h +++ b/xbmc/GUIInfoManager.h @@ -103,7 +103,7 @@ namespace INFO #define PLAYER_FILEPATH 46 #define PLAYER_SEEKOFFSET 47 #define PLAYER_PROGRESS_CACHE 48 -#define PLAYER_ITEM_PROPERTY 49 +#define PLAYER_ITEM_ART 49 #define PLAYER_CAN_PAUSE 50 #define PLAYER_CAN_SEEK 51 @@ -614,11 +614,12 @@ namespace INFO #define LISTITEM_PROGRESS (LISTITEM_START + 102) #define LISTITEM_HAS_EPG (LISTITEM_START + 103) -#define LISTITEM_PROPERTY_START (LISTITEM_START + 200) +#define LISTITEM_PROPERTY_START (LISTITEM_START + 100) #define LISTITEM_PROPERTY_END (LISTITEM_PROPERTY_START + 1000) #define LISTITEM_END (LISTITEM_PROPERTY_END) -#define MUSICPLAYER_PROPERTY_OFFSET 900 // last 100 id's reserved for musicplayer props. +#define MUSICPLAYER_PROPERTY_OFFSET 800 // 100 id's reserved for musicplayer props. +#define LISTITEM_ART_OFFSET 900 // 100 id's reserved for listitem art. #define CONDITIONAL_LABEL_START LISTITEM_END + 1 // 36001 #define CONDITIONAL_LABEL_END 37000 diff --git a/xbmc/TextureCache.cpp b/xbmc/TextureCache.cpp index 239dd41138..2f5b9f5280 100644 --- a/xbmc/TextureCache.cpp +++ b/xbmc/TextureCache.cpp @@ -311,6 +311,23 @@ void CTextureCache::OnJobProgress(unsigned int jobID, unsigned int progress, uns CJobQueue::OnJobProgress(jobID, progress, total, job); } +bool CTextureCache::Export(const CStdString &image, const CStdString &destination, bool overwrite) +{ + CStdString cachedHash; + CStdString cachedImage(GetCachedImage(image, cachedHash)); + if (!cachedImage.IsEmpty()) + { + CStdString dest = URIUtils::ReplaceExtension(destination, URIUtils::GetExtension(cachedImage)); + if (overwrite || !CFile::Exists(dest)) + { + if (CFile::Cache(cachedImage, dest)) + return true; + CLog::Log(LOGERROR, "%s failed exporting '%s' to '%s'", __FUNCTION__, cachedImage.c_str(), dest.c_str()); + } + } + return false; +} + bool CTextureCache::Export(const CStdString &image, const CStdString &destination) { CStdString cachedHash; diff --git a/xbmc/TextureCache.h b/xbmc/TextureCache.h index 228bb7892c..81ac2d0165 100644 --- a/xbmc/TextureCache.h +++ b/xbmc/TextureCache.h @@ -137,10 +137,12 @@ public: /*! \brief Export a (possibly) cached image to a file \param image url of the original image - \param destination url of the destination image + \param destination url of the destination image, excluding extension. + \param overwrite whether to overwrite the destination if it exists (TODO: Defaults to false) \return true if we successfully exported the file, false otherwise. */ - bool Export(const CStdString &image, const CStdString &destination); + bool Export(const CStdString &image, const CStdString &destination, bool overwrite); + bool Export(const CStdString &image, const CStdString &destination); // TODO: BACKWARD COMPATIBILITY FOR MUSIC THUMBS private: // private construction, and no assignements; use the provided singleton methods CTextureCache(); diff --git a/xbmc/ThumbLoader.cpp b/xbmc/ThumbLoader.cpp index 8c35847c60..45d6b3913c 100644 --- a/xbmc/ThumbLoader.cpp +++ b/xbmc/ThumbLoader.cpp @@ -128,7 +128,7 @@ bool CThumbExtractor::DoWork() CTextureCache::Get().AddCachedTexture(m_target, details); m_item.SetProperty("HasAutoThumb", true); m_item.SetProperty("AutoThumbImage", m_target); - m_item.SetThumbnailImage(CTextureCache::GetCachedPath(details.file)); + m_item.SetArt("thumb", CTextureCache::GetCachedPath(details.file)); } } else if (m_item.HasVideoInfoTag() && !m_item.GetVideoInfoTag()->HasStreamDetails()) @@ -188,6 +188,17 @@ static void SetupRarOptions(CFileItem& item, const CStdString& path) g_directoryCache.ClearDirectory(url.GetWithoutFilename()); } +vector<string> CVideoThumbLoader::GetArtTypes(const string &type) +{ + vector<string> ret; + ret.push_back("fanart"); + ret.push_back("poster"); + if (type == "tvshow" || type == "season" || type.empty()) + ret.push_back("banner"); + ret.push_back("thumb"); + return ret; +} + /** * Look for a thumbnail for pItem. If one does not exist, look for an autogenerated * thumbnail. If that does not exist, attempt to autogenerate one. Finally, check @@ -226,52 +237,55 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem) } } - // fanart - if (!pItem->HasProperty("fanart_image")) + // if we have no art, look for it all + map<string, string> artwork = pItem->GetArt(); + if (artwork.empty()) { - CStdString fanart = GetCachedImage(*pItem, "fanart"); - if (fanart.IsEmpty()) + vector<string> artTypes = GetArtTypes(pItem->HasVideoInfoTag() ? pItem->GetVideoInfoTag()->m_type : ""); + for (vector<string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i) { - fanart = pItem->GetLocalFanart(); - if (!fanart.IsEmpty()) // cache it - SetCachedImage(*pItem, "fanart", fanart); - } - if (!fanart.IsEmpty()) - { - CTextureCache::Get().BackgroundCacheImage(fanart); - pItem->SetProperty("fanart_image", fanart); + std::string type = *i; + std::string art = GetCachedImage(*pItem, type); + if (art.empty()) + { + art = GetLocalArt(*pItem, type, type=="fanart"); + if (!art.empty()) // cache it + SetCachedImage(*pItem, type, art); + } + if (!art.empty()) + { + CTextureCache::Get().BackgroundCacheImage(art); + artwork.insert(make_pair(type, art)); + } } + pItem->SetArt(artwork); } - // thumbnails - if (!pItem->HasThumbnail()) + // thumbnails are special-cased due to auto-generation + if (!pItem->HasArt("thumb") && !pItem->m_bIsFolder && pItem->IsVideo()) { - FillThumb(*pItem); - if (!pItem->HasThumbnail() && !pItem->m_bIsFolder && pItem->IsVideo()) + // create unique thumb for auto generated thumbs + CStdString thumbURL = GetEmbeddedThumbURL(*pItem); + if (CTextureCache::Get().HasCachedImage(thumbURL)) { - // create unique thumb for auto generated thumbs - CStdString thumbURL = GetEmbeddedThumbURL(*pItem); - if (CTextureCache::Get().HasCachedImage(thumbURL)) - { - CTextureCache::Get().BackgroundCacheImage(thumbURL); - pItem->SetProperty("HasAutoThumb", true); - pItem->SetProperty("AutoThumbImage", thumbURL); - pItem->SetThumbnailImage(thumbURL); - } - else if (g_guiSettings.GetBool("myvideos.extractthumb") && - g_guiSettings.GetBool("myvideos.extractflags")) - { - CFileItem item(*pItem); - CStdString path(item.GetPath()); - if (URIUtils::IsInRAR(item.GetPath())) - SetupRarOptions(item,path); + CTextureCache::Get().BackgroundCacheImage(thumbURL); + pItem->SetProperty("HasAutoThumb", true); + pItem->SetProperty("AutoThumbImage", thumbURL); + pItem->SetArt("thumb", thumbURL); + } + else if (g_guiSettings.GetBool("myvideos.extractthumb") && + g_guiSettings.GetBool("myvideos.extractflags")) + { + CFileItem item(*pItem); + CStdString path(item.GetPath()); + if (URIUtils::IsInRAR(item.GetPath())) + SetupRarOptions(item,path); - CThumbExtractor* extract = new CThumbExtractor(item, path, true, thumbURL); - AddJob(extract); + CThumbExtractor* extract = new CThumbExtractor(item, path, true, thumbURL); + AddJob(extract); - m_database->Close(); - return true; - } + m_database->Close(); + return true; } } @@ -355,7 +369,7 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) tag.m_strPictureURL.Parse(); CStdString thumb = CScraperUrl::GetThumbURL(tag.m_strPictureURL.GetFirstThumb()); if (!thumb.IsEmpty()) - item.SetThumbnailImage(thumb); + item.SetArt("thumb", thumb); } } else if (tag.m_type == "season") @@ -368,7 +382,7 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) CVideoInfoScanner::GetSeasonThumbs(show, seasons, true); map<int, string>::iterator season = seasons.find(tag.m_iSeason); if (season != seasons.end()) - item.SetThumbnailImage(season->second); + item.SetArt("thumb", season->second); } // add to the database for next time around map<string, string> artwork = item.GetArt(); @@ -382,16 +396,16 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) m_database->SetArtForItem(tag.m_iDbId, tag.m_type, "thumb", ""); } // For episodes and seasons, we want to set fanart for that of the show - if (!item.HasProperty("fanart_image") && tag.m_iIdShow >= 0) + if (!item.HasArt("fanart") && tag.m_iIdShow >= 0) { map<string, string> showArt; if (m_database->GetArtForItem(tag.m_iIdShow, "tvshow", showArt)) { map<string, string>::iterator i = showArt.find("fanart"); if (i != showArt.end()) - item.SetProperty("fanart_image", i->second); + item.SetArt("fanart", i->second); if ((i = showArt.find("thumb")) != showArt.end()) - item.SetProperty("tvshowthumb", i->second); + item.SetArt("tvshowthumb", i->second); } } m_database->Close(); @@ -401,19 +415,41 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) bool CVideoThumbLoader::FillThumb(CFileItem &item) { - if (item.HasThumbnail()) + if (item.HasArt("thumb")) return true; CStdString thumb = GetCachedImage(item, "thumb"); if (thumb.IsEmpty()) { - thumb = item.GetUserVideoThumb(); + thumb = GetLocalArt(item, "thumb"); if (!thumb.IsEmpty()) SetCachedImage(item, "thumb", thumb); } - item.SetThumbnailImage(thumb); + item.SetArt("thumb", thumb); return !thumb.IsEmpty(); } +std::string CVideoThumbLoader::GetLocalArt(const CFileItem &item, const std::string &type, bool checkFolder) +{ + std::string art; + if (!type.empty()) + { + art = item.FindLocalArt(type + ".jpg", checkFolder); + if (art.empty()) + art = item.FindLocalArt(type + ".png", checkFolder); + } + if (art.empty() && (type.empty() || type == "thumb")) + { // backward compatibility + art = item.FindLocalArt("", false); + if (art.empty() && (checkFolder || (item.m_bIsFolder && !item.IsFileFolder()))) + { // try movie.tbn + art = item.FindLocalArt("movie.tbn", true); + if (art.empty()) // try folder.jpg + art = item.FindLocalArt("folder.jpg", true); + } + } + return art; +} + CStdString CVideoThumbLoader::GetEmbeddedThumbURL(const CFileItem &item) { CStdString path(item.GetPath()); @@ -460,7 +496,7 @@ bool CProgramThumbLoader::LoadItem(CFileItem *pItem) bool CProgramThumbLoader::FillThumb(CFileItem &item) { // no need to do anything if we already have a thumb set - CStdString thumb = item.GetThumbnailImage(); + CStdString thumb = item.GetArt("thumb"); if (thumb.IsEmpty()) { // see whether we have a cached image for this item @@ -476,7 +512,7 @@ bool CProgramThumbLoader::FillThumb(CFileItem &item) if (!thumb.IsEmpty()) { CTextureCache::Get().BackgroundCacheImage(thumb); - item.SetThumbnailImage(thumb); + item.SetArt("thumb", thumb); } return true; } @@ -537,7 +573,7 @@ bool CMusicThumbLoader::LoadItem(CFileItem* pItem) return true; // no fallback } - if (!pItem->HasProperty("fanart_image")) + if (!pItem->HasArt("fanart")) { if (pItem->HasMusicInfoTag() && !pItem->GetMusicInfoTag()->GetArtist().empty()) { @@ -548,13 +584,13 @@ bool CMusicThumbLoader::LoadItem(CFileItem* pItem) { string fanart = m_database->GetArtForItem(idArtist, "artist", "fanart"); if (!fanart.empty()) - pItem->SetProperty("fanart_image", fanart); + pItem->SetArt("fanart", fanart); } m_database->Close(); } } - if (!pItem->HasThumbnail()) + if (!pItem->HasArt("thumb")) FillThumb(*pItem); return true; @@ -562,7 +598,7 @@ bool CMusicThumbLoader::LoadItem(CFileItem* pItem) bool CMusicThumbLoader::FillThumb(CFileItem &item) { - if (item.HasThumbnail()) + if (item.HasArt("thumb")) return true; CStdString thumb = GetCachedImage(item, "thumb"); if (thumb.IsEmpty()) @@ -571,7 +607,7 @@ bool CMusicThumbLoader::FillThumb(CFileItem &item) if (!thumb.IsEmpty()) SetCachedImage(item, "thumb", thumb); } - item.SetThumbnailImage(thumb); + item.SetArt("thumb", thumb); return !thumb.IsEmpty(); } @@ -611,7 +647,7 @@ bool CMusicThumbLoader::FillLibraryArt(CFileItem &item) } if (tag.GetType() == "song" || tag.GetType() == "album") { // fanart from the artist - item.SetProperty("fanart_image", m_database->GetArtistArtForItem(tag.GetDatabaseId(), tag.GetType(), "fanart")); + item.SetArt("fanart", m_database->GetArtistArtForItem(tag.GetDatabaseId(), tag.GetType(), "fanart")); } m_database->Close(); } diff --git a/xbmc/ThumbLoader.h b/xbmc/ThumbLoader.h index 4411cfa615..f75d384f19 100644 --- a/xbmc/ThumbLoader.h +++ b/xbmc/ThumbLoader.h @@ -111,6 +111,21 @@ public: */ static bool FillThumb(CFileItem &item); + /*! \brief Find a particular art type for a given item, optionally checking at the folder level + \param item the CFileItem to search. + \param type the type of art to look for. + \param checkFolder whether to also check the folder level for files. Defaults to false. + \return the art file (if found), else empty. + */ + static std::string GetLocalArt(const CFileItem &item, const std::string &type, bool checkFolder = false); + + /*! \brief return the available art types for a given media type + \param type the type of media. + \return a vector of art types. + \sa GetLocalArt + */ + static std::vector<std::string> GetArtTypes(const std::string &type); + /*! \brief helper function to retrieve a thumb URL for embedded video thumbs \param item a video CFileItem. \return a URL for the embedded thumb. diff --git a/xbmc/addons/AddonCallbacksGUI.cpp b/xbmc/addons/AddonCallbacksGUI.cpp index 5b4cd3339e..df0702c74f 100644 --- a/xbmc/addons/AddonCallbacksGUI.cpp +++ b/xbmc/addons/AddonCallbacksGUI.cpp @@ -1112,7 +1112,7 @@ GUIHANDLE CAddonCallbacksGUI::ListItem_Create(void *addonData, const char *label if (iconImage) pItem->SetIconImage(iconImage); if (thumbnailImage) - pItem->SetThumbnailImage(thumbnailImage); + pItem->SetArt("thumb", thumbnailImage); if (path) pItem->SetPath(path); @@ -1177,7 +1177,7 @@ void CAddonCallbacksGUI::ListItem_SetThumbnailImage(void *addonData, GUIHANDLE h if (!helper || !handle) return; - ((CFileItem*)handle)->SetThumbnailImage(image); + ((CFileItem*)handle)->SetArt("thumb", image); } void CAddonCallbacksGUI::ListItem_SetInfo(void *addonData, GUIHANDLE handle, const char *info) diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp index eb0ee8826a..ee0a7a1266 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp @@ -245,7 +245,7 @@ bool CDVDInputStreamHTSP::UpdateItem(CFileItem& item) } CFileItem current(item); CHTSPSession::ParseItem(channel, m_tag, m_event, item); - item.SetThumbnailImage(channel.icon); + item.SetArt("thumb", channel.icon); return current.GetPath() != item.GetPath() || current.m_strTitle != item.m_strTitle; } diff --git a/xbmc/dialogs/GUIDialogContextMenu.cpp b/xbmc/dialogs/GUIDialogContextMenu.cpp index 95db351250..3c4e599a8d 100644 --- a/xbmc/dialogs/GUIDialogContextMenu.cpp +++ b/xbmc/dialogs/GUIDialogContextMenu.cpp @@ -493,14 +493,14 @@ bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileI if (!share->m_strThumbnailImage.IsEmpty()) { CFileItemPtr current(new CFileItem("thumb://Current", false)); - current->SetThumbnailImage(share->m_strThumbnailImage); + current->SetArt("thumb", share->m_strThumbnailImage); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } - else if (item->HasThumbnail()) + else if (item->HasArt("thumb")) { // already have a thumb that the share doesn't know about - must be a local one, so we mayaswell reuse it. CFileItemPtr current(new CFileItem("thumb://Current", false)); - current->SetThumbnailImage(item->GetThumbnailImage()); + current->SetArt("thumb", item->GetArt("thumb")); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } @@ -509,7 +509,7 @@ bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileI if (XFILE::CFile::Exists(folderThumb)) { CFileItemPtr local(new CFileItem("thumb://Local", false)); - local->SetThumbnailImage(folderThumb); + local->SetArt("thumb", folderThumb); local->SetLabel(g_localizeStrings.Get(20017)); items.Add(local); } diff --git a/xbmc/dialogs/GUIDialogFavourites.cpp b/xbmc/dialogs/GUIDialogFavourites.cpp index 36e08843b9..628cb68f42 100644 --- a/xbmc/dialogs/GUIDialogFavourites.cpp +++ b/xbmc/dialogs/GUIDialogFavourites.cpp @@ -199,10 +199,10 @@ void CGUIDialogFavourites::OnSetThumb(int item) CFileItemList items; // Current - if (pItem->HasThumbnail()) + if (pItem->HasArt("thumb")) { CFileItemPtr current(new CFileItem("thumb://Current", false)); - current->SetThumbnailImage(pItem->GetThumbnailImage()); + current->SetArt("thumb", pItem->GetArt("thumb")); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } @@ -219,7 +219,7 @@ void CGUIDialogFavourites::OnSetThumb(int item) if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(1030), thumb)) return; - (*m_favourites)[item]->SetThumbnailImage(thumb); + (*m_favourites)[item]->SetArt("thumb", thumb); CFavourites::Save(*m_favourites); UpdateList(); } diff --git a/xbmc/dialogs/GUIDialogMediaSource.cpp b/xbmc/dialogs/GUIDialogMediaSource.cpp index 31f2a4c63e..e3afeefa26 100644 --- a/xbmc/dialogs/GUIDialogMediaSource.cpp +++ b/xbmc/dialogs/GUIDialogMediaSource.cpp @@ -153,7 +153,7 @@ bool CGUIDialogMediaSource::ShowAndAddMediaSource(const CStdString &type) } share.FromNameAndPaths(type, strName, dialog->GetPaths()); if (dialog->m_paths->Size() > 0) { - share.m_strThumbnailImage = dialog->m_paths->Get(0)->GetThumbnailImage(); + share.m_strThumbnailImage = dialog->m_paths->Get(0)->GetArt("thumb"); } g_settings.AddShare(type, share); } diff --git a/xbmc/filesystem/AddonsDirectory.cpp b/xbmc/filesystem/AddonsDirectory.cpp index f78b05bde1..9118c84113 100644 --- a/xbmc/filesystem/AddonsDirectory.cpp +++ b/xbmc/filesystem/AddonsDirectory.cpp @@ -145,7 +145,7 @@ bool CAddonsDirectory::GetDirectory(const CStdString& strPath, CFileItemList &it item->m_bIsFolder = true; CStdString thumb = GetIcon((TYPE)i); if (!thumb.IsEmpty() && g_TextureManager.HasTexture(thumb)) - item->SetThumbnailImage(thumb); + item->SetArt("thumb", thumb); items.Add(item); break; } @@ -251,14 +251,14 @@ CFileItemPtr CAddonsDirectory::FileItemFromAddon(AddonPtr &addon, const CStdStri if (!(basePath.Equals("addons://") && addon->Type() == ADDON_REPOSITORY)) item->SetLabel2(addon->Version().c_str()); - item->SetThumbnailImage(addon->Icon()); + item->SetArt("thumb", addon->Icon()); item->SetLabelPreformated(true); item->SetIconImage("DefaultAddon.png"); if (!addon->FanArt().IsEmpty() && (URIUtils::IsInternetStream(addon->FanArt()) || CFile::Exists(addon->FanArt()))) { - item->SetProperty("fanart_image", addon->FanArt()); + item->SetArt("fanart", addon->FanArt()); } CAddonDatabase::SetPropertiesFromAddon(addon, item); return item; diff --git a/xbmc/filesystem/AndroidAppDirectory.cpp b/xbmc/filesystem/AndroidAppDirectory.cpp index 8ab2ad0fa2..12db2a5243 100644 --- a/xbmc/filesystem/AndroidAppDirectory.cpp +++ b/xbmc/filesystem/AndroidAppDirectory.cpp @@ -66,7 +66,7 @@ bool CAndroidAppDirectory::GetDirectory(const CStdString& strPath, CFileItemList path.Format("androidapp://%s/%s/%s", url.GetHostName(), dirname, applications[i].packageName); pItem->SetPath(path); pItem->SetLabel(applications[i].packageLabel); - pItem->SetThumbnailImage(path+".png"); + pItem->SetArt("thumb", path+".png"); items.Add(pItem); } return true; diff --git a/xbmc/filesystem/HTSPDirectory.cpp b/xbmc/filesystem/HTSPDirectory.cpp index a14b06820e..d6c406712d 100644 --- a/xbmc/filesystem/HTSPDirectory.cpp +++ b/xbmc/filesystem/HTSPDirectory.cpp @@ -453,7 +453,7 @@ bool CHTSPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &item item->SetPath(url.Get()); item->SetLabel(label); item->SetLabelPreformated(true); - item->SetThumbnailImage(it->second.icon); + item->SetArt("thumb", it->second.icon); items.Add(item); } diff --git a/xbmc/filesystem/HTSPSession.cpp b/xbmc/filesystem/HTSPSession.cpp index b0ea9b6174..34cb6dfa48 100644 --- a/xbmc/filesystem/HTSPSession.cpp +++ b/xbmc/filesystem/HTSPSession.cpp @@ -642,7 +642,7 @@ bool CHTSPSession::ParseItem(const SChannel& channel, int tagid, const SEvent& e item.SetPath(url.Get()); item.m_strTitle = tag->m_strTitle; - item.SetThumbnailImage(channel.icon); + item.SetArt("thumb", channel.icon); item.SetMimeType("video/X-htsp"); return true; } diff --git a/xbmc/filesystem/MusicDatabaseDirectory.cpp b/xbmc/filesystem/MusicDatabaseDirectory.cpp index 687c299d5f..8df83d7c92 100644 --- a/xbmc/filesystem/MusicDatabaseDirectory.cpp +++ b/xbmc/filesystem/MusicDatabaseDirectory.cpp @@ -52,7 +52,7 @@ bool CMusicDatabaseDirectory::GetDirectory(const CStdString& strPath, CFileItemL for (int i=0;i<items.Size();++i) { CFileItemPtr item = items[i]; - if (item->m_bIsFolder && !item->HasIcon() && !item->HasThumbnail()) + if (item->m_bIsFolder && !item->HasIcon() && !item->HasArt("thumb")) { CStdString strImage = GetIcon(item->GetPath()); if (!strImage.IsEmpty() && g_TextureManager.HasTexture(strImage)) diff --git a/xbmc/filesystem/MythDirectory.cpp b/xbmc/filesystem/MythDirectory.cpp index 983b623000..553db0196b 100644 --- a/xbmc/filesystem/MythDirectory.cpp +++ b/xbmc/filesystem/MythDirectory.cpp @@ -141,7 +141,7 @@ bool CMythDirectory::GetGuide(const CStdString& base, CFileItemList &items) if (!icon.IsEmpty()) { url.SetFileName("files/channels/" + URIUtils::GetFileName(icon)); // e.g. files/channels/tv3.jpg - item->SetThumbnailImage(url.Get()); + item->SetArt("thumb", url.Get()); } items.Add(item); diff --git a/xbmc/filesystem/MythSession.cpp b/xbmc/filesystem/MythSession.cpp index 7b155db6ce..cec07b2e30 100644 --- a/xbmc/filesystem/MythSession.cpp +++ b/xbmc/filesystem/MythSession.cpp @@ -235,7 +235,7 @@ void CMythSession::SetFileItemMetaData(CFileItem &item, cmyth_proginfo_t program if (!chanicon.IsEmpty()) { url.SetFileName("files/channels/" + URIUtils::GetFileName(chanicon)); // e.g. files/channels/tv3.jpg - item.SetThumbnailImage(url.Get()); + item.SetArt("thumb", url.Get()); } } else @@ -246,7 +246,7 @@ void CMythSession::SetFileItemMetaData(CFileItem &item, cmyth_proginfo_t program if (m_dll->proginfo_rec_status(program) == RS_RECORDED) { url.SetFileName("files/" + URIUtils::GetFileName(GetValue(m_dll->proginfo_pathname(program))) + ".png"); - item.SetThumbnailImage(url.Get()); + item.SetArt("thumb", url.Get()); } } } diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp index 24205d46f6..6c084fd7c2 100644 --- a/xbmc/filesystem/PluginDirectory.cpp +++ b/xbmc/filesystem/PluginDirectory.cpp @@ -613,7 +613,10 @@ void CPluginDirectory::SetProperty(int handle, const CStdString &strProperty, co } CPluginDirectory *dir = globalHandles[handle]; - dir->m_listItems->SetProperty(strProperty, strValue); + if (strProperty == "fanart_image") + dir->m_listItems->SetArt("fanart", strValue); + else + dir->m_listItems->SetProperty(strProperty, strValue); } void CPluginDirectory::CancelDirectory() diff --git a/xbmc/filesystem/RSSDirectory.cpp b/xbmc/filesystem/RSSDirectory.cpp index 343c87434f..646ae082a6 100644 --- a/xbmc/filesystem/RSSDirectory.cpp +++ b/xbmc/filesystem/RSSDirectory.cpp @@ -168,12 +168,12 @@ static void ParseItemMRSS(CFileItem* item, SResources& resources, TiXmlElement* else if(name == "thumbnail") { if(item_child->GetText() && IsPathToThumbnail(item_child->GetText())) - item->SetThumbnailImage(item_child->GetText()); + item->SetArt("thumb", item_child->GetText()); else { const char * url = item_child->Attribute("url"); if(url && IsPathToThumbnail(url)) - item->SetThumbnailImage(url); + item->SetArt("thumb", url); } } else if (name == "title") @@ -263,9 +263,9 @@ static void ParseItemItunes(CFileItem* item, SResources& resources, TiXmlElement { const char * url = item_child->Attribute("href"); if(url) - item->SetThumbnailImage(url); + item->SetArt("thumb", url); else - item->SetThumbnailImage(text); + item->SetArt("thumb", text); } else if(name == "summary") vtag->m_strPlot = text; @@ -359,9 +359,9 @@ static void ParseItemVoddler(CFileItem* item, SResources& resources, TiXmlElemen { const char* url = element->Attribute("url"); if(url) - item->SetProperty("fanart_image", url); + item->SetArt("fanart", url); else if(IsPathToThumbnail(text)) - item->SetProperty("fanart_image", text); + item->SetArt("fanart", text); } } @@ -371,7 +371,7 @@ static void ParseItemBoxee(CFileItem* item, SResources& resources, TiXmlElement* CStdString text = element->GetText(); if (name == "image") - item->SetThumbnailImage(text); + item->SetArt("thumb", text); else if(name == "user_agent") item->SetProperty("boxee:user_agent", text); else if(name == "content_type") @@ -630,10 +630,8 @@ bool CRSSDirectory::GetDirectory(const CStdString& path, CFileItemList &items) item->SetProperty("isrss", "1"); // Use channel image if item doesn't have one - if(item->GetThumbnailImage().IsEmpty() && !items.GetThumbnailImage().IsEmpty()) - { - item->SetThumbnailImage(items.GetThumbnailImage()); - } + if (!item->HasArt("thumb") && items.HasArt("thumb")) + item->SetArt("thumb", items.GetArt("thumb")); if (!item->GetPath().IsEmpty()) items.Add(item); diff --git a/xbmc/filesystem/SourcesDirectory.cpp b/xbmc/filesystem/SourcesDirectory.cpp index 11d1615541..4b56eae590 100644 --- a/xbmc/filesystem/SourcesDirectory.cpp +++ b/xbmc/filesystem/SourcesDirectory.cpp @@ -75,7 +75,7 @@ bool CSourcesDirectory::GetDirectory(const VECSOURCES &sources, CFileItemList &i // CDetectDVDMedia::SetNewDVDShareUrl() caches disc thumb as special://temp/dvdicon.tbn CStdString strThumb = "special://temp/dvdicon.tbn"; if (XFILE::CFile::Exists(strThumb)) - pItem->SetThumbnailImage(strThumb); + pItem->SetArt("thumb", strThumb); } else if (pItem->GetPath().Left(9) == "addons://") strIcon = "DefaultHardDisk.png"; diff --git a/xbmc/filesystem/UPnPDirectory.cpp b/xbmc/filesystem/UPnPDirectory.cpp index d6690b3789..7ce87d1122 100644 --- a/xbmc/filesystem/UPnPDirectory.cpp +++ b/xbmc/filesystem/UPnPDirectory.cpp @@ -275,7 +275,7 @@ CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) CFileItemPtr pItem(new CFileItem((const char*)name)); pItem->SetPath(CStdString((const char*) "upnp://" + uuid + "/")); pItem->m_bIsFolder = true; - pItem->SetThumbnailImage((const char*)(*device)->GetIconUrl("image/jpeg")); + pItem->SetArt("thumb", (const char*)(*device)->GetIconUrl("image/jpeg")); items.Add(pItem); @@ -460,15 +460,15 @@ CUPnPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) // if there is a thumbnail available set it here if((*entry)->m_ExtraInfo.album_arts.GetItem(0)) // only considers first album art - pItem->SetThumbnailImage((const char*) (*entry)->m_ExtraInfo.album_arts.GetItem(0)->uri); + pItem->SetArt("thumb", (const char*) (*entry)->m_ExtraInfo.album_arts.GetItem(0)->uri); else if((*entry)->m_Description.icon_uri.GetLength()) - pItem->SetThumbnailImage((const char*) (*entry)->m_Description.icon_uri); + pItem->SetArt("thumb", (const char*) (*entry)->m_Description.icon_uri); PLT_ProtocolInfo fanart_mask("xbmc.org", "*", "fanart", "*"); for(unsigned i = 0; i < (*entry)->m_Resources.GetItemCount(); ++i) { PLT_MediaItemResource& res = (*entry)->m_Resources[i]; if(res.m_ProtocolInfo.Match(fanart_mask)) { - pItem->SetProperty("fanart_image", (const char*)res.m_Uri); + pItem->SetArt("fanart", (const char*)res.m_Uri); break; } } diff --git a/xbmc/filesystem/VideoDatabaseDirectory.cpp b/xbmc/filesystem/VideoDatabaseDirectory.cpp index 793c0f0b56..33a7139c97 100644 --- a/xbmc/filesystem/VideoDatabaseDirectory.cpp +++ b/xbmc/filesystem/VideoDatabaseDirectory.cpp @@ -53,7 +53,7 @@ bool CVideoDatabaseDirectory::GetDirectory(const CStdString& strPath, CFileItemL for (int i=0;i<items.Size();++i) { CFileItemPtr item = items[i]; - if (item->m_bIsFolder && !item->HasIcon() && !item->HasThumbnail()) + if (item->m_bIsFolder && !item->HasIcon() && !item->HasArt("thumb")) { CStdString strImage = GetIcon(item->GetPath()); if (!strImage.IsEmpty() && g_TextureManager.HasTexture(strImage)) diff --git a/xbmc/guilib/GUIListItem.cpp b/xbmc/guilib/GUIListItem.cpp index 52a8f619f0..5f7111fce7 100644 --- a/xbmc/guilib/GUIListItem.cpp +++ b/xbmc/guilib/GUIListItem.cpp @@ -41,7 +41,6 @@ CGUIListItem::CGUIListItem(void) m_strLabel = ""; m_bSelected = false; m_strIcon = ""; - m_strThumbnailImage = ""; m_overlayIcon = ICON_OVERLAY_NONE; m_layout = NULL; m_focusedLayout = NULL; @@ -55,7 +54,6 @@ CGUIListItem::CGUIListItem(const CStdString& strLabel) SetSortLabel(strLabel); m_bSelected = false; m_strIcon = ""; - m_strThumbnailImage = ""; m_overlayIcon = ICON_OVERLAY_NONE; m_layout = NULL; m_focusedLayout = NULL; @@ -111,17 +109,28 @@ const CStdStringW& CGUIListItem::GetSortLabel() const return m_sortLabel; } -void CGUIListItem::SetThumbnailImage(const CStdString& strThumbnail) +void CGUIListItem::SetArt(const std::string &type, const std::string &url) { - if (m_strThumbnailImage == strThumbnail) - return; - m_strThumbnailImage = strThumbnail; - SetInvalid(); + ArtMap::iterator i = m_art.find(type); + if (i == m_art.end() || i->second != url) + { + m_art[type] = url; + SetInvalid(); + } +} + +std::string CGUIListItem::GetArt(const std::string &type) const +{ + ArtMap::const_iterator i = m_art.find(type); + if (i != m_art.end()) + return i->second; + return ""; } -const CStdString& CGUIListItem::GetThumbnailImage() const +bool CGUIListItem::HasArt(const std::string &type) const { - return m_strThumbnailImage; + ArtMap::const_iterator i = m_art.find(type); + return (i != m_art.end() && !i->second.empty()); } void CGUIListItem::SetIconImage(const CStdString& strIcon) @@ -171,23 +180,22 @@ CStdString CGUIListItem::GetOverlayImage() const } } -map<string, string> CGUIListItem::GetArt() const +const map<string, string> &CGUIListItem::GetArt() const { - map<string, string> art; - if (HasThumbnail()) - art.insert(make_pair("thumb", GetThumbnailImage())); - if (HasProperty("fanart_image")) - art.insert(make_pair("fanart", GetProperty("fanart_image").asString())); - return art; + return m_art; } void CGUIListItem::SetArt(const map<string, string> &art) { - map<string, string>::const_iterator i = art.find("thumb"); - if (i != art.end()) - SetThumbnailImage(i->second); - if ((i = art.find("fanart")) != art.end()) - SetProperty("fanart_image", i->second); + m_art = art; + // ensure that the fallback "thumb" is available + if (m_art.find("thumb") == m_art.end()) + { + if (HasArt("poster")) + m_art["thumb"] = m_art["poster"]; + else if (HasArt("banner")) + m_art["thumb"] = m_art["banner"]; + } } void CGUIListItem::Select(bool bOnOff) @@ -200,12 +208,6 @@ bool CGUIListItem::HasIcon() const return (m_strIcon.size() != 0); } - -bool CGUIListItem::HasThumbnail() const -{ - return (m_strThumbnailImage.size() != 0); -} - bool CGUIListItem::HasOverlay() const { return (m_overlayIcon != CGUIListItem::ICON_OVERLAY_NONE); @@ -225,10 +227,10 @@ const CGUIListItem& CGUIListItem::operator =(const CGUIListItem& item) FreeMemory(); m_bSelected = item.m_bSelected; m_strIcon = item.m_strIcon; - m_strThumbnailImage = item.m_strThumbnailImage; m_overlayIcon = item.m_overlayIcon; m_bIsFolder = item.m_bIsFolder; m_mapProperties = item.m_mapProperties; + m_art = item.m_art; SetInvalid(); return *this; } @@ -241,7 +243,6 @@ void CGUIListItem::Archive(CArchive &ar) ar << m_strLabel; ar << m_strLabel2; ar << m_sortLabel; - ar << m_strThumbnailImage; ar << m_strIcon; ar << m_bSelected; ar << m_overlayIcon; @@ -251,6 +252,12 @@ void CGUIListItem::Archive(CArchive &ar) ar << it->first; ar << it->second; } + ar << (int)m_art.size(); + for (ArtMap::const_iterator i = m_art.begin(); i != m_art.end(); i++) + { + ar << i->first; + ar << i->second; + } } else { @@ -258,7 +265,6 @@ void CGUIListItem::Archive(CArchive &ar) ar >> m_strLabel; ar >> m_strLabel2; ar >> m_sortLabel; - ar >> m_strThumbnailImage; ar >> m_strIcon; ar >> m_bSelected; @@ -270,12 +276,20 @@ void CGUIListItem::Archive(CArchive &ar) ar >> mapSize; for (int i = 0; i < mapSize; i++) { - CStdString key; + std::string key; CVariant value; ar >> key; ar >> value; SetProperty(key, value); } + ar >> mapSize; + for (int i = 0; i < mapSize; i++) + { + std::string key, value; + ar >> key; + ar >> value; + m_art.insert(make_pair(key, value)); + } } } void CGUIListItem::Serialize(CVariant &value) @@ -284,7 +298,6 @@ void CGUIListItem::Serialize(CVariant &value) value["strLabel"] = m_strLabel; value["strLabel2"] = m_strLabel2; value["sortLabel"] = m_sortLabel; - value["strThumbnailImage"] = m_strThumbnailImage; value["strIcon"] = m_strIcon; value["selected"] = m_bSelected; @@ -292,12 +305,16 @@ void CGUIListItem::Serialize(CVariant &value) { value["properties"][it->first] = it->second; } + for (ArtMap::const_iterator it = m_art.begin(); it != m_art.end(); it++) + value["art"][it->first] = it->second; } void CGUIListItem::FreeIcons() { FreeMemory(); - m_strThumbnailImage = ""; + ArtMap::iterator i = m_art.find("thumb"); + if (i != m_art.end()) + m_art.erase(i); m_strIcon = ""; SetInvalid(); } diff --git a/xbmc/guilib/GUIListItem.h b/xbmc/guilib/GUIListItem.h index 930ebe2a91..9e353309d7 100644 --- a/xbmc/guilib/GUIListItem.h +++ b/xbmc/guilib/GUIListItem.h @@ -45,6 +45,8 @@ class CVariant; class CGUIListItem { public: + typedef std::map<std::string, std::string> ArtMap; + enum GUIIconOverlay { ICON_OVERLAY_NONE = 0, ICON_OVERLAY_RAR, ICON_OVERLAY_ZIP, @@ -72,25 +74,40 @@ public: void SetIconImage(const CStdString& strIcon); const CStdString& GetIconImage() const; - void SetThumbnailImage(const CStdString& strThumbnail); - const CStdString& GetThumbnailImage() const; - void SetOverlayImage(GUIIconOverlay icon, bool bOnOff=false); CStdString GetOverlayImage() const; + /*! \brief Set a particular art type for an item + \param type type of art to set. + \param url the url of the art. + */ + void SetArt(const std::string &type, const std::string &url); + /*! \brief set artwork for an item - Sets thumb and fanart image \param map a type:url map for artwork \sa GetArt */ - void SetArt(const std::map<std::string, std::string> &art); + void SetArt(const ArtMap &art); + + /*! \brief Get a particular art type for an item + \param type type of art to fetch. + \return the art URL, if available, else empty. + */ + std::string GetArt(const std::string &type) const; /*! \brief get artwork for an item Retrieves artwork in a type:url map \return a type:url map for artwork \sa SetArt */ - std::map<std::string, std::string> GetArt() const; + const ArtMap &GetArt() const; + + /*! \brief Check whether an item has a particular piece of art + Equivalent to !GetArt(type).empty() + \param type type of art to set. + \return true if the item has that art set, false otherwise. + */ + bool HasArt(const std::string &type) const; void SetSortLabel(const CStdString &label); void SetSortLabel(const CStdStringW &label); @@ -100,7 +117,6 @@ public: bool IsSelected() const; bool HasIcon() const; - bool HasThumbnail() const; bool HasOverlay() const; virtual bool IsFileItem() const { return false; }; @@ -141,7 +157,6 @@ public: protected: CStdString m_strLabel2; // text of column2 - CStdString m_strThumbnailImage; // filename of thumbnail CStdString m_strIcon; // filename of icon GUIIconOverlay m_overlayIcon; // type of overlay icon @@ -162,6 +177,8 @@ protected: private: CStdStringW m_sortLabel; // text for sorting. Need to be UTF16 for proper sorting CStdString m_strLabel; // text of column1 + + ArtMap m_art; }; #endif diff --git a/xbmc/guilib/GUIStaticItem.cpp b/xbmc/guilib/GUIStaticItem.cpp index 7028aac4fe..26d28ae096 100644 --- a/xbmc/guilib/GUIStaticItem.cpp +++ b/xbmc/guilib/GUIStaticItem.cpp @@ -49,7 +49,7 @@ CGUIStaticItem::CGUIStaticItem(const TiXmlElement *item, int parentID) : CFileIt CGUIControlFactory::GetActions(item, "onclick", m_clickActions); SetLabel(label.GetLabel(parentID)); SetLabel2(label2.GetLabel(parentID)); - SetThumbnailImage(thumb.GetLabel(parentID, true)); + SetArt("thumb", thumb.GetLabel(parentID, true)); SetIconImage(icon.GetLabel(parentID, true)); if (!label.IsConstant()) m_info.push_back(make_pair(label, "label")); if (!label2.IsConstant()) m_info.push_back(make_pair(label2, "label2")); @@ -82,7 +82,7 @@ CGUIStaticItem::CGUIStaticItem(const TiXmlElement *item, int parentID) : CFileIt SetLabel(CGUIInfoLabel::GetLabel(label, parentID)); SetPath(item->FirstChild()->Value()); SetLabel2(CGUIInfoLabel::GetLabel(label2, parentID)); - SetThumbnailImage(CGUIInfoLabel::GetLabel(thumb, parentID, true)); + SetArt("thumb", CGUIInfoLabel::GetLabel(thumb, parentID, true)); SetIconImage(CGUIInfoLabel::GetLabel(icon, parentID, true)); m_iprogramCount = id ? atoi(id) : 0; } @@ -101,7 +101,7 @@ void CGUIStaticItem::UpdateProperties(int contextWindow) else if (name.Equals("label2")) SetLabel2(value); else if (name.Equals("thumb")) - SetThumbnailImage(value); + SetArt("thumb", value); else if (name.Equals("icon")) SetIconImage(value); else diff --git a/xbmc/interfaces/http-api/XBMChttp.cpp b/xbmc/interfaces/http-api/XBMChttp.cpp index f01b710bf6..4c376d3651 100644 --- a/xbmc/interfaces/http-api/XBMChttp.cpp +++ b/xbmc/interfaces/http-api/XBMChttp.cpp @@ -1203,8 +1203,8 @@ int CXbmcHttp::xbmcGetTagFromFilename(int numParas, CStdString paras[]) tmp.Format("%i", stTime.wYear); output += closeTag+openTag+"Release year:" + tmp; CMusicThumbLoader::FillThumb(*pItem); - if (pItem->HasThumbnail()) - output += closeTag+openTag+"Thumb:" + pItem->GetThumbnailImage() ; + if (pItem->HasArt("thumb")) + output += closeTag+openTag+"Thumb:" + (CStdString)pItem->GetArt("thumb"); else { output += closeTag+openTag+"Thumb:[None]"; } @@ -1272,7 +1272,7 @@ int CXbmcHttp::xbmcGetMovieDetails(int numParas, CStdString paras[]) if (!CVideoThumbLoader::FillThumb(*item)) thumb = "[None]"; else - thumb = CTextureCache::GetWrappedImageURL(item->GetThumbnailImage()); + thumb = CTextureCache::GetWrappedImageURL(item->GetArt("thumb")); output += closeTag+openTag+"Thumb:" + thumb; m_database.Close(); delete item; diff --git a/xbmc/interfaces/json-rpc/FileItemHandler.cpp b/xbmc/interfaces/json-rpc/FileItemHandler.cpp index 1cbc29898b..11887af4c0 100644 --- a/xbmc/interfaces/json-rpc/FileItemHandler.cpp +++ b/xbmc/interfaces/json-rpc/FileItemHandler.cpp @@ -86,17 +86,17 @@ bool CFileItemHandler::GetField(const std::string &field, const CVariant &info, if (field == "thumbnail") { - if (thumbLoader != NULL && !item->HasThumbnail() && !fetchedArt && + if (thumbLoader != NULL && !item->HasArt("thumb") && !fetchedArt && ((item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > -1) || (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > -1))) { thumbLoader->FillLibraryArt(*item); fetchedArt = true; } - else if (item->HasPictureInfoTag() && !item->HasThumbnail()) - item->SetThumbnailImage(CTextureCache::GetWrappedThumbURL(item->GetPath())); + else if (item->HasPictureInfoTag() && !item->HasArt("thumb")) + item->SetArt("thumb", CTextureCache::GetWrappedThumbURL(item->GetPath())); - if (item->HasThumbnail()) - result["thumbnail"] = CTextureCache::GetWrappedImageURL(item->GetThumbnailImage()); + if (item->HasArt("thumb")) + result["thumbnail"] = CTextureCache::GetWrappedImageURL(item->GetArt("thumb")); else result["thumbnail"] = ""; @@ -105,15 +105,15 @@ bool CFileItemHandler::GetField(const std::string &field, const CVariant &info, if (field == "fanart") { - if (thumbLoader != NULL && !item->HasProperty("fanart_image") && !fetchedArt && + if (thumbLoader != NULL && !item->HasArt("fanart") && !fetchedArt && ((item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_iDbId > -1) || (item->HasMusicInfoTag() && item->GetMusicInfoTag()->GetDatabaseId() > -1))) { thumbLoader->FillLibraryArt(*item); fetchedArt = true; } - if (item->HasProperty("fanart_image")) - result["fanart"] = CTextureCache::GetWrappedImageURL(item->GetProperty("fanart_image").asString()); + if (item->HasArt("fanart")) + result["fanart"] = CTextureCache::GetWrappedImageURL(item->GetArt("fanart")); else result["fanart"] = ""; diff --git a/xbmc/interfaces/legacy/ListItem.cpp b/xbmc/interfaces/legacy/ListItem.cpp index d273adb12b..8416616ec1 100644 --- a/xbmc/interfaces/legacy/ListItem.cpp +++ b/xbmc/interfaces/legacy/ListItem.cpp @@ -56,7 +56,7 @@ namespace XBMCAddon if (!iconImage.empty()) item->SetIconImage( iconImage ); if (!thumbnailImage.empty()) - item->SetThumbnailImage( thumbnailImage ); + item->SetArt("thumb", thumbnailImage ); if (!path.empty()) item->SetPath(path); } @@ -126,7 +126,7 @@ namespace XBMCAddon if (!item) return; { LOCKGUI; - item->SetThumbnailImage(thumbFilename); + item->SetArt("thumb", thumbFilename); } } diff --git a/xbmc/music/LastFmManager.cpp b/xbmc/music/LastFmManager.cpp index d06801d2f6..90e5941a6f 100644 --- a/xbmc/music/LastFmManager.cpp +++ b/xbmc/music/LastFmManager.cpp @@ -382,7 +382,7 @@ bool CLastFmManager::RequestRadioTracks() CStdString coverUrl = child->Value(); if ((coverUrl != "") && (coverUrl.Find("noimage") == -1) && (coverUrl.Right(1) != "/")) { - newItem->SetThumbnailImage(coverUrl); + newItem->SetArt("thumb", coverUrl); } } } @@ -423,9 +423,9 @@ void CLastFmManager::CacheTrackThumb(const int nrInitialTracksToAdd) CFileItemPtr item = (*m_RadioTrackQueue)[i]; if (!item->GetMusicInfoTag()->Loaded()) { - if (!item->HasThumbnail()) + if (!item->HasArt("thumb")) { - item->SetThumbnailImage("DefaultAlbumCover.png"); + item->SetArt("thumb", "DefaultAlbumCover.png"); } item->GetMusicInfoTag()->SetLoaded(); } diff --git a/xbmc/music/MusicInfoLoader.cpp b/xbmc/music/MusicInfoLoader.cpp index b7b5b2ee3f..d202c11d8b 100644 --- a/xbmc/music/MusicInfoLoader.cpp +++ b/xbmc/music/MusicInfoLoader.cpp @@ -132,7 +132,7 @@ bool CMusicInfoLoader::LoadItem(CFileItem* pItem) if (mapItem && mapItem->m_dateTime==pItem->m_dateTime && mapItem->HasMusicInfoTag() && mapItem->GetMusicInfoTag()->Loaded()) { // Query map if we previously cached the file on HD *pItem->GetMusicInfoTag() = *mapItem->GetMusicInfoTag(); - pItem->SetThumbnailImage(mapItem->GetThumbnailImage()); + pItem->SetArt("thumb", mapItem->GetArt("thumb")); return true; } @@ -152,7 +152,7 @@ bool CMusicInfoLoader::LoadItem(CFileItem* pItem) if ((song=m_songsMap.Find(pItem->GetPath()))!=NULL) { // Have we loaded this item from database before pItem->GetMusicInfoTag()->SetSong(*song); - pItem->SetThumbnailImage(song->strThumb); + pItem->SetArt("thumb", song->strThumb); } else if (pItem->IsMusicDb()) { // a music db item that doesn't have tag loaded - grab details from the database @@ -162,7 +162,7 @@ bool CMusicInfoLoader::LoadItem(CFileItem* pItem) if (m_musicDatabase.GetSongById(param.GetSongId(), song)) { pItem->GetMusicInfoTag()->SetSong(song); - pItem->SetThumbnailImage(song.strThumb); + pItem->SetArt("thumb", song.strThumb); } } else if (g_guiSettings.GetBool("musicfiles.usetags") || pItem->IsCDDA()) @@ -195,8 +195,7 @@ void CMusicInfoLoader::OnLoaderFinish() for (int i = 0; i < m_pVecItems->Size(); ++i) { CSong song(*m_pVecItems->Get(i)->GetMusicInfoTag()); - if (m_pVecItems->Get(i)->HasThumbnail()) - song.strThumb = m_pVecItems->Get(i)->GetThumbnailImage(); + song.strThumb = m_pVecItems->Get(i)->GetArt("thumb"); song.idSong = i; // for the lookup below songs.push_back(song); } @@ -209,9 +208,9 @@ void CMusicInfoLoader::OnLoaderFinish() for (VECSONGS::iterator j = i->songs.begin(); j != i->songs.end(); ++j) { if (!j->strThumb.empty()) - m_pVecItems->Get(j->idSong)->SetThumbnailImage(j->strThumb); + m_pVecItems->Get(j->idSong)->SetArt("thumb", j->strThumb); else - m_pVecItems->Get(j->idSong)->SetThumbnailImage(albumArt); + m_pVecItems->Get(j->idSong)->SetArt("thumb", albumArt); } } } diff --git a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp index 8f93bdf58f..c26b07170c 100644 --- a/xbmc/music/dialogs/GUIDialogMusicInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogMusicInfo.cpp @@ -173,7 +173,7 @@ void CGUIDialogMusicInfo::SetAlbum(const CAlbum& album, const CStdString &path) if (artwork.find("thumb") != artwork.end()) m_albumItem->SetProperty("artistthumb", artwork["thumb"]); if (artwork.find("fanart") != artwork.end()) - m_albumItem->SetProperty("fanart_image",artwork["fanart"]); + m_albumItem->SetArt("fanart",artwork["fanart"]); } } m_hasUpdatedThumb = false; @@ -226,9 +226,9 @@ void CGUIDialogMusicInfo::SetDiscography() long idAlbum = database.GetAlbumByName(item->GetLabel(),m_artist.strArtist); if (idAlbum != -1) // we need this slight stupidity to get correct case for the album name - item->SetThumbnailImage(database.GetArtForItem(idAlbum, "album", "thumb")); + item->SetArt("thumb", database.GetArtForItem(idAlbum, "album", "thumb")); else - item->SetThumbnailImage("DefaultAlbumCover.png"); + item->SetArt("thumb", "DefaultAlbumCover.png"); m_albumSongs->Add(item); } @@ -290,7 +290,7 @@ void CGUIDialogMusicInfo::Update() { CGUIImage* pImageControl = (CGUIImage*)pControl; pImageControl->FreeResources(); - pImageControl->SetFileName(m_albumItem->GetThumbnailImage()); + pImageControl->SetFileName(m_albumItem->GetArt("thumb")); } // disable the GetThumb button if the user isn't allowed it @@ -343,10 +343,10 @@ void CGUIDialogMusicInfo::OnGetThumb() CFileItemList items; // Current thumb - if (CFile::Exists(m_albumItem->GetThumbnailImage())) + if (CFile::Exists(m_albumItem->GetArt("thumb"))) { CFileItemPtr item(new CFileItem("thumb://Current", false)); - item->SetThumbnailImage(m_albumItem->GetThumbnailImage()); + item->SetArt("thumb", m_albumItem->GetArt("thumb")); item->SetLabel(g_localizeStrings.Get(20016)); items.Add(item); } @@ -363,7 +363,7 @@ void CGUIDialogMusicInfo::OnGetThumb() CStdString strItemPath; strItemPath.Format("thumb://Remote%i", i); CFileItemPtr item(new CFileItem(strItemPath, false)); - item->SetThumbnailImage(thumbs[i]); + item->SetArt("thumb", thumbs[i]); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20015)); @@ -387,7 +387,7 @@ void CGUIDialogMusicInfo::OnGetThumb() if (CFile::Exists(localThumb)) { CFileItemPtr item(new CFileItem("thumb://Local", false)); - item->SetThumbnailImage(localThumb); + item->SetArt("thumb", localThumb); item->SetLabel(g_localizeStrings.Get(20017)); items.Add(item); } @@ -433,7 +433,7 @@ void CGUIDialogMusicInfo::OnGetThumb() db.Close(); } - m_albumItem->SetThumbnailImage(newThumb); + m_albumItem->SetArt("thumb", newThumb); m_hasUpdatedThumb = true; // tell our GUI to completely reload all controls (as some of them @@ -450,10 +450,10 @@ void CGUIDialogMusicInfo::OnGetFanart() { CFileItemList items; - if (m_albumItem->HasProperty("fanart_image")) + if (m_albumItem->HasArt("fanart")) { CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); - itemCurrent->SetThumbnailImage(m_albumItem->GetProperty("fanart_image").asString()); + itemCurrent->SetArt("thumb", m_albumItem->GetArt("fanart")); itemCurrent->SetLabel(g_localizeStrings.Get(20440)); items.Add(itemCurrent); } @@ -465,7 +465,7 @@ void CGUIDialogMusicInfo::OnGetFanart() strItemPath.Format("fanart://Remote%i",i); CFileItemPtr item(new CFileItem(strItemPath, false)); CStdString thumb = m_artist.fanart.GetPreviewURL(i); - item->SetThumbnailImage(CTextureCache::GetWrappedThumbURL(thumb)); + item->SetArt("thumb", CTextureCache::GetWrappedThumbURL(thumb)); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20441)); @@ -484,7 +484,7 @@ void CGUIDialogMusicInfo::OnGetFanart() if (!strLocal.IsEmpty()) { CFileItemPtr itemLocal(new CFileItem("fanart://Local",false)); - itemLocal->SetThumbnailImage(strLocal); + itemLocal->SetArt("thumb", strLocal); itemLocal->SetLabel(g_localizeStrings.Get(20438)); // TODO: Do we need to clear the cached image? @@ -534,10 +534,7 @@ void CGUIDialogMusicInfo::OnGetFanart() db.Close(); } - if (!result.empty()) - m_albumItem->SetProperty("fanart_image",result); - else - m_albumItem->ClearProperty("fanart_image"); + m_albumItem->SetArt("fanart", result); m_hasUpdatedThumb = true; // tell our GUI to completely reload all controls (as some of them // are likely to have had this image in use so will need refreshing) diff --git a/xbmc/music/dialogs/GUIDialogSongInfo.cpp b/xbmc/music/dialogs/GUIDialogSongInfo.cpp index beb93e078a..db81d6688a 100644 --- a/xbmc/music/dialogs/GUIDialogSongInfo.cpp +++ b/xbmc/music/dialogs/GUIDialogSongInfo.cpp @@ -241,16 +241,16 @@ void CGUIDialogSongInfo::OnGetThumb() if (DownloadThumbnail(thumbFromWeb)) { CFileItemPtr item(new CFileItem("thumb://allmusic.com", false)); - item->SetThumbnailImage(thumbFromWeb); + item->SetArt("thumb", thumbFromWeb); item->SetLabel(g_localizeStrings.Get(20055)); items.Add(item); }*/ // Current thumb - if (CFile::Exists(m_song->GetThumbnailImage())) + if (CFile::Exists(m_song->GetArt("thumb"))) { CFileItemPtr item(new CFileItem("thumb://Current", false)); - item->SetThumbnailImage(m_song->GetThumbnailImage()); + item->SetArt("thumb", m_song->GetArt("thumb")); item->SetLabel(g_localizeStrings.Get(20016)); items.Add(item); } @@ -266,7 +266,7 @@ void CGUIDialogSongInfo::OnGetThumb() if (CFile::Exists(localThumb)) { CFileItemPtr item(new CFileItem("thumb://Local", false)); - item->SetThumbnailImage(localThumb); + item->SetArt("thumb", localThumb); item->SetLabel(g_localizeStrings.Get(20017)); items.Add(item); } @@ -275,7 +275,7 @@ void CGUIDialogSongInfo::OnGetThumb() // which is probably the allmusic.com thumb. These could be wrong, so allow the user // to delete the incorrect thumb CFileItemPtr item(new CFileItem("thumb://None", false)); - item->SetThumbnailImage("DefaultAlbumCover.png"); + item->SetArt("thumb", "DefaultAlbumCover.png"); item->SetLabel(g_localizeStrings.Get(20018)); items.Add(item); } @@ -308,7 +308,7 @@ void CGUIDialogSongInfo::OnGetThumb() db.Close(); } - m_song->SetThumbnailImage(newThumb); + m_song->SetArt("thumb", newThumb); // tell our GUI to completely reload all controls (as some of them // are likely to have had this image in use so will need refreshing) diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp index 9e6fcf8054..552813dbc2 100644 --- a/xbmc/music/windows/GUIWindowMusicBase.cpp +++ b/xbmc/music/windows/GUIWindowMusicBase.cpp @@ -1336,7 +1336,7 @@ bool CGUIWindowMusicBase::GetDirectory(const CStdString &strDirectory, CFileItem directory = musicUrl.ToString(); } - items.SetThumbnailImage(""); + items.SetArt("thumb", ""); bool bResult = CGUIMediaWindow::GetDirectory(directory, items); if (bResult) CMusicThumbLoader::FillThumb(items); diff --git a/xbmc/network/GUIDialogAccessPoints.cpp b/xbmc/network/GUIDialogAccessPoints.cpp index 2b5705c41a..e04d276357 100644 --- a/xbmc/network/GUIDialogAccessPoints.cpp +++ b/xbmc/network/GUIDialogAccessPoints.cpp @@ -92,11 +92,11 @@ void CGUIDialogAccessPoints::OnInitWindow() CFileItemPtr item(new CFileItem(m_aps[i].getEssId())); int q = m_aps[i].getQuality(); - if (q <= 20) item->SetThumbnailImage("ap-signal1.png"); - else if (q <= 40) item->SetThumbnailImage("ap-signal2.png"); - else if (q <= 60) item->SetThumbnailImage("ap-signal3.png"); - else if (q <= 80) item->SetThumbnailImage("ap-signal4.png"); - else if (q <= 100) item->SetThumbnailImage("ap-signal5.png"); + if (q <= 20) item->SetArt("thumb", "ap-signal1.png"); + else if (q <= 40) item->SetArt("thumb", "ap-signal2.png"); + else if (q <= 60) item->SetArt("thumb", "ap-signal3.png"); + else if (q <= 80) item->SetArt("thumb", "ap-signal4.png"); + else if (q <= 100) item->SetArt("thumb", "ap-signal5.png"); if (m_aps[i].getEncryptionMode() != ENC_NONE) item->SetIconImage("ap-lock.png"); diff --git a/xbmc/network/upnp/UPnPInternal.cpp b/xbmc/network/upnp/UPnPInternal.cpp index 8acb55dc0c..87ff9e02ac 100644 --- a/xbmc/network/upnp/UPnPInternal.cpp +++ b/xbmc/network/upnp/UPnPInternal.cpp @@ -511,14 +511,14 @@ BuildObject(const CFileItem& item, } } // set a thumbnail if we have one - if (item.HasThumbnail() && upnp_server) { + if (item.HasArt("thumb") && upnp_server) { PLT_AlbumArtInfo art; art.uri = upnp_server->BuildSafeResourceUri( rooturi, (*ips.GetFirstItem()).ToString(), - item.GetThumbnailImage()); + item.GetArt("thumb").c_str()); // Set DLNA profileID by extension, defaulting to JPEG. - NPT_String ext = URIUtils::GetExtension(item.GetThumbnailImage()).c_str(); + NPT_String ext = URIUtils::GetExtension(item.GetArt("thumb")).c_str(); if (strcmp(ext, ".png") == 0) { art.dlna_profile = "PNG_TN"; } else { @@ -528,8 +528,8 @@ BuildObject(const CFileItem& item, } if (upnp_server) { - if (item.HasProperty("fanart_image")) { - upnp_server->AddSafeResourceUri(object, rooturi, ips, item.GetProperty("fanart_image").asString().c_str(), "xbmc.org:*:fanart:*" ); + if (item.HasArt("fanart")) { + upnp_server->AddSafeResourceUri(object, rooturi, ips, item.GetArt("fanart").c_str(), "xbmc.org:*:fanart:*" ); } } diff --git a/xbmc/network/upnp/UPnPRenderer.cpp b/xbmc/network/upnp/UPnPRenderer.cpp index f409357b52..bb43bbc698 100644 --- a/xbmc/network/upnp/UPnPRenderer.cpp +++ b/xbmc/network/upnp/UPnPRenderer.cpp @@ -476,7 +476,7 @@ CUPnPRenderer::PlayMedia(const char* uri, const char* meta, PLT_Action* action) item.SetLabelPreformated(true); if (object->m_ExtraInfo.album_arts.GetItem(0)) { //FIXME only considers 1st image - item.SetThumbnailImage((const char*)object->m_ExtraInfo.album_arts.GetItem(0)->uri); + item.SetArt("thumb", (const char*)object->m_ExtraInfo.album_arts.GetItem(0)->uri); } if (object->m_ObjectClass.type.StartsWith("object.item.audioItem")) { if(NPT_SUCCEEDED(PopulateTagFromObject(*item.GetMusicInfoTag(), *object, res))) diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp index 2008582b28..c4b873fa3b 100644 --- a/xbmc/network/upnp/UPnPServer.cpp +++ b/xbmc/network/upnp/UPnPServer.cpp @@ -118,8 +118,8 @@ CUPnPServer::Build(CFileItemPtr item, if (!item->HasMusicInfoTag()) item->LoadMusicTag(); - if (!item->HasThumbnail() ) - item->SetThumbnailImage(CThumbLoader::GetCachedImage(*item, "thumb")); + if (!item->HasArt("thumb") ) + item->SetArt("thumb", CThumbLoader::GetCachedImage(*item, "thumb")); if (item->GetLabel().IsEmpty()) { /* if no label try to grab it from node type */ @@ -165,8 +165,8 @@ CUPnPServer::Build(CFileItemPtr item, } } - if (!item->HasThumbnail() ) - item->SetThumbnailImage(CThumbLoader::GetCachedImage(*item, "thumb")); + if (!item->HasArt("thumb") ) + item->SetArt("thumb", CThumbLoader::GetCachedImage(*item, "thumb")); } } diff --git a/xbmc/pictures/GUIWindowPictures.cpp b/xbmc/pictures/GUIWindowPictures.cpp index 2ff413f3b5..f9df4a01b1 100644 --- a/xbmc/pictures/GUIWindowPictures.cpp +++ b/xbmc/pictures/GUIWindowPictures.cpp @@ -264,10 +264,10 @@ bool CGUIWindowPictures::Update(const CStdString &strDirectory) if (!CGUIMediaWindow::Update(strDirectory)) return false; - m_vecItems->SetThumbnailImage(""); + m_vecItems->SetArt("thumb", ""); if (g_guiSettings.GetBool("pictures.generatethumbs")) m_thumbLoader.Load(*m_vecItems); - m_vecItems->SetThumbnailImage(CPictureThumbLoader::GetCachedImage(*m_vecItems, "thumb")); + m_vecItems->SetArt("thumb", CPictureThumbLoader::GetCachedImage(*m_vecItems, "thumb")); return true; } diff --git a/xbmc/pictures/PictureInfoLoader.cpp b/xbmc/pictures/PictureInfoLoader.cpp index 1f0e3dced9..8b07d8e56f 100644 --- a/xbmc/pictures/PictureInfoLoader.cpp +++ b/xbmc/pictures/PictureInfoLoader.cpp @@ -64,7 +64,7 @@ bool CPictureInfoLoader::LoadItem(CFileItem* pItem) if (mapItem && mapItem->m_dateTime==pItem->m_dateTime && mapItem->HasPictureInfoTag()) { // Query map if we previously cached the file on HD *pItem->GetPictureInfoTag() = *mapItem->GetPictureInfoTag(); - pItem->SetThumbnailImage(mapItem->GetThumbnailImage()); + pItem->SetArt("thumb", mapItem->GetArt("thumb")); return true; } diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp index 18983895b8..c6a5a57fb0 100644 --- a/xbmc/pictures/PictureThumbLoader.cpp +++ b/xbmc/pictures/PictureThumbLoader.cpp @@ -50,19 +50,19 @@ bool CPictureThumbLoader::LoadItem(CFileItem* pItem) if (pItem->m_bIsShareOrDrive) return true; if (pItem->IsParentFolder()) return true; - if (pItem->HasThumbnail() && m_regenerateThumbs) + if (pItem->HasArt("thumb") && m_regenerateThumbs) { - CTextureCache::Get().ClearCachedImage(pItem->GetThumbnailImage()); + CTextureCache::Get().ClearCachedImage(pItem->GetArt("thumb")); CTextureDatabase db; if (db.Open()) db.ClearTextureForPath(pItem->GetPath(), "thumb"); - pItem->SetThumbnailImage(""); + pItem->SetArt("thumb", ""); } CStdString thumb; if (pItem->IsPicture() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList()) { // load the thumb from the image file - thumb = pItem->HasThumbnail() ? pItem->GetThumbnailImage() : CTextureCache::GetWrappedThumbURL(pItem->GetPath()); + thumb = pItem->HasArt("thumb") ? pItem->GetArt("thumb") : CTextureCache::GetWrappedThumbURL(pItem->GetPath()); } else if (pItem->IsVideo() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList()) { // video @@ -82,14 +82,14 @@ bool CPictureThumbLoader::LoadItem(CFileItem* pItem) } } } - else if (!pItem->HasThumbnail()) + else if (!pItem->HasArt("thumb")) { // folder, zip, cbz, rar, cbr, playlist may have a previously cached image thumb = GetCachedImage(*pItem, "thumb"); } if (!thumb.IsEmpty()) { CTextureCache::Get().BackgroundCacheImage(thumb); - pItem->SetThumbnailImage(thumb); + pItem->SetArt("thumb", thumb); } pItem->FillInDefaultIcon(); return true; @@ -116,7 +116,7 @@ void CPictureThumbLoader::OnLoaderFinish() void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) { - if (pItem->HasThumbnail()) + if (pItem->HasArt("thumb")) return; CTextureDatabase db; @@ -128,7 +128,7 @@ void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) { db.SetTextureForPath(pItem->GetPath(), "thumb", strTBN); CTextureCache::Get().BackgroundCacheImage(strTBN); - pItem->SetThumbnailImage(strTBN); + pItem->SetArt("thumb", strTBN); return; } } @@ -154,7 +154,7 @@ void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) { db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); CTextureCache::Get().BackgroundCacheImage(thumb); - pItem->SetThumbnailImage(thumb); + pItem->SetArt("thumb", thumb); return; } if (!pItem->IsPlugin()) @@ -190,7 +190,7 @@ void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) if (item->m_bIsFolder) { ProcessFoldersAndArchives(item.get()); - pItem->SetThumbnailImage(items[i]->GetThumbnailImage()); + pItem->SetArt("thumb", items[i]->GetArt("thumb")); pItem->SetIconImage(items[i]->GetIconImage()); return; } @@ -208,7 +208,7 @@ void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) CStdString thumb = CTextureCache::GetWrappedThumbURL(items[0]->GetPath()); db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); CTextureCache::Get().BackgroundCacheImage(thumb); - pItem->SetThumbnailImage(thumb); + pItem->SetArt("thumb", thumb); } else { @@ -227,7 +227,7 @@ void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) details.height = g_advancedSettings.GetThumbSize(); CTextureCache::Get().AddCachedTexture(thumb, details); db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); - pItem->SetThumbnailImage(CTextureCache::GetCachedPath(relativeCacheFile)); + pItem->SetArt("thumb", CTextureCache::GetCachedPath(relativeCacheFile)); } } } diff --git a/xbmc/pvr/channels/PVRChannelGroup.cpp b/xbmc/pvr/channels/PVRChannelGroup.cpp index 5d1b023cc4..a46eec9ac2 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.cpp +++ b/xbmc/pvr/channels/PVRChannelGroup.cpp @@ -1013,7 +1013,7 @@ int CPVRChannelGroup::GetEPGNow(CFileItemList &results) CFileItemPtr entry(new CFileItem(epgNow)); entry->SetLabel2(epgNow.StartAsLocalTime().GetAsLocalizedTime(StringUtils::EmptyString, false)); entry->SetPath(channel->ChannelName()); - entry->SetThumbnailImage(channel->IconPath()); + entry->SetArt("thumb", channel->IconPath()); results.Add(entry); } @@ -1039,7 +1039,7 @@ int CPVRChannelGroup::GetEPGNext(CFileItemList &results) CFileItemPtr entry(new CFileItem(epgNow)); entry->SetLabel2(epgNow.StartAsLocalTime().GetAsLocalizedTime(StringUtils::EmptyString, false)); entry->SetPath(channel->ChannelName()); - entry->SetThumbnailImage(channel->IconPath()); + entry->SetArt("thumb", channel->IconPath()); results.Add(entry); } diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp index 254f482dea..e503e46bf2 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelManager.cpp @@ -325,14 +325,14 @@ bool CGUIDialogPVRChannelManager::OnClickButtonChannelLogo(CGUIMessage &message) if (!pItem->GetProperty("Icon").asString().empty()) { CFileItemPtr current(new CFileItem("thumb://Current", false)); - current->SetThumbnailImage(pItem->GetPVRChannelInfoTag()->IconPath()); + current->SetArt("thumb", pItem->GetPVRChannelInfoTag()->IconPath()); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } - else if (pItem->HasThumbnail()) + else if (pItem->HasArt("thumb")) { // already have a thumb that the share doesn't know about - must be a local one, so we mayaswell reuse it. CFileItemPtr current(new CFileItem("thumb://Current", false)); - current->SetThumbnailImage(pItem->GetThumbnailImage()); + current->SetArt("thumb", pItem->GetArt("thumb")); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } diff --git a/xbmc/pvr/recordings/PVRRecordings.cpp b/xbmc/pvr/recordings/PVRRecordings.cpp index 91f7badada..534a623767 100644 --- a/xbmc/pvr/recordings/PVRRecordings.cpp +++ b/xbmc/pvr/recordings/PVRRecordings.cpp @@ -112,10 +112,10 @@ void CPVRRecordings::GetContents(const CStdString &strDirectory, CFileItemList * pFileItem->SetIconImage(current->m_strIconPath); if (!current->m_strThumbnailPath.IsEmpty()) - pFileItem->SetThumbnailImage(current->m_strThumbnailPath); + pFileItem->SetArt("thumb", current->m_strThumbnailPath); if (!current->m_strFanartPath.IsEmpty()) - pFileItem->SetProperty("Fanart_Image", current->m_strFanartPath); + pFileItem->SetArt("fanart", current->m_strFanartPath); // Set the play count either directly from client (if supported) or from video db if (g_PVRClients->SupportsRecordingPlayCount(pFileItem->GetPVRRecordingInfoTag()->m_iClientId)) @@ -463,7 +463,7 @@ bool CPVRRecordings::GetDirectory(const CStdString& strPath, CFileItemList &item { CFileItemPtr pFileItem = files.Get(i); CFileItemPtr pThumbItem = items.Get(pFileItem->GetPath()); - if (!pThumbItem->HasThumbnail()) + if (!pThumbItem->HasArt("thumb")) m_thumbLoader.LoadItem(pThumbItem.get()); } } diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp index fdc84086aa..01e95504a5 100644 --- a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp @@ -458,15 +458,15 @@ bool CGUIWindowPVRChannels::OnContextButtonSetThumb(CFileItem *item, CONTEXT_BUT { /* add the current thumb, if available */ CFileItemPtr current(new CFileItem("thumb://Current", false)); - current->SetThumbnailImage(channel->IconPath()); + current->SetArt("thumb", channel->IconPath()); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } - else if (item->HasThumbnail()) + else if (item->HasArt("thumb")) { /* already have a thumb that the share doesn't know about - must be a local one, so we may as well reuse it */ CFileItemPtr current(new CFileItem("thumb://Current", false)); - current->SetThumbnailImage(item->GetThumbnailImage()); + current->SetArt("thumb", item->GetArt("thumb")); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } diff --git a/xbmc/settings/GUIDialogContentSettings.cpp b/xbmc/settings/GUIDialogContentSettings.cpp index 7f501d953e..0204039c71 100644 --- a/xbmc/settings/GUIDialogContentSettings.cpp +++ b/xbmc/settings/GUIDialogContentSettings.cpp @@ -320,7 +320,7 @@ void CGUIDialogContentSettings::FillListControl() { CFileItemPtr item(new CFileItem((*iter)->Name())); item->SetPath((*iter)->ID()); - item->SetThumbnailImage((*iter)->Icon()); + item->SetArt("thumb", (*iter)->Icon()); if (m_scraper && (*iter)->ID() == m_scraper->ID()) { item->Select(true); diff --git a/xbmc/settings/GUIDialogProfileSettings.cpp b/xbmc/settings/GUIDialogProfileSettings.cpp index 4ff4f0ea36..d34237b3e9 100644 --- a/xbmc/settings/GUIDialogProfileSettings.cpp +++ b/xbmc/settings/GUIDialogProfileSettings.cpp @@ -157,12 +157,12 @@ void CGUIDialogProfileSettings::OnSettingChanged(SettingInfo &setting) if (!m_strThumb.IsEmpty()) { CFileItemPtr item(new CFileItem("thumb://Current", false)); - item->SetThumbnailImage(m_strThumb); + item->SetArt("thumb", m_strThumb); item->SetLabel(g_localizeStrings.Get(20016)); items.Add(item); } CFileItemPtr item(new CFileItem("thumb://None", false)); - item->SetThumbnailImage(m_strDefaultImage); + item->SetArt("thumb", m_strDefaultImage); item->SetLabel(g_localizeStrings.Get(20018)); items.Add(item); if (CGUIDialogFileBrowser::ShowAndGetImage(items,shares,g_localizeStrings.Get(1030),strThumb) && diff --git a/xbmc/settings/GUIWindowSettingsProfile.cpp b/xbmc/settings/GUIWindowSettingsProfile.cpp index 85bb96e2cb..9d4929b1c9 100644 --- a/xbmc/settings/GUIWindowSettingsProfile.cpp +++ b/xbmc/settings/GUIWindowSettingsProfile.cpp @@ -183,7 +183,7 @@ void CGUIWindowSettingsProfile::LoadList() const CProfile *profile = g_settings.GetProfile(i); CFileItemPtr item(new CFileItem(profile->getName())); item->SetLabel2(profile->getDate()); - item->SetThumbnailImage(profile->getThumb()); + item->SetArt("thumb", profile->getThumb()); item->SetOverlayImage(profile->getLockMode() == LOCK_MODE_EVERYONE ? CGUIListItem::ICON_OVERLAY_NONE : CGUIListItem::ICON_OVERLAY_LOCKED); m_listItems->Add(item); } diff --git a/xbmc/test/Makefile b/xbmc/test/Makefile index 76541e9eb8..7b485f68dc 100644 --- a/xbmc/test/Makefile +++ b/xbmc/test/Makefile @@ -1,5 +1,6 @@ SRCS= \ TestBasicEnvironment.cpp \ + TestFileItem.cpp \ TestUtils.cpp \ xbmc-test.cpp diff --git a/xbmc/test/TestFileItem.cpp b/xbmc/test/TestFileItem.cpp new file mode 100644 index 0000000000..03c1d8a007 --- /dev/null +++ b/xbmc/test/TestFileItem.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2005-2012 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "FileItem.h" +#include "URL.h" +#include "settings/AdvancedSettings.h" + +#include "gtest/gtest.h" + +TEST(TestFileItem, GetLocalArt) +{ + typedef struct + { + const char *file; + bool use_folder; + const char *base; + } testfiles; + + const testfiles test_files[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\filename-art.jpg" }, + { "c:\\dir\\filename.avi", true, "c:\\dir\\art.jpg" }, + { "/dir/filename.avi", false, "/dir/filename-art.jpg" }, + { "/dir/filename.avi", true, "/dir/art.jpg" }, + { "smb://somepath/file.avi", false, "smb://somepath/file-art.jpg" }, + { "smb://somepath/file.avi", true, "smb://somepath/art.jpg" }, + { "stack:///path/to/movie-cd1.avi , /path/to/movie-cd2.avi", false, "/path/to/movie-art.jpg" }, + { "stack:///path/to/movie-cd1.avi , /path/to/movie-cd2.avi", true, "/path/to/art.jpg" }, + { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", true, "/path/to/movie_name/art.jpg" }, + { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01-art.jpg" }, + { "/home/user/TV Shows/Dexter/S1/1x01.avi", true, "/home/user/TV Shows/Dexter/S1/art.jpg" }, + { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", false, "g:\\multimedia\\movies\\Sphere-art.jpg" }, + { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", true, "g:\\multimedia\\movies\\art.jpg" }, + { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", false, "/home/user/movies/movie_name/art.jpg" }, + { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", true, "/home/user/movies/movie_name/art.jpg" }, + { "/home/user/movies/movie_name/BDMV/index.bdmv", false, "/home/user/movies/movie_name/art.jpg" }, + { "/home/user/movies/movie_name/BDMV/index.bdmv", true, "/home/user/movies/movie_name/art.jpg" }}; + + const testfiles test_file2[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\filename.tbn" }, + { "/dir/filename.avi", false, "/dir/filename.tbn" }, + { "smb://somepath/file.avi", false, "smb://somepath/file.tbn" }, + { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01.tbn" }, + { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", false, "g:\\multimedia\\movies\\Sphere.tbn" }}; + + g_advancedSettings.Initialize(); + + for (unsigned int i = 0; i < sizeof(test_files) / sizeof(testfiles); i++) + { + CFileItem item; + item.SetPath(test_files[i].file); + std::string path = CURL(item.GetLocalArt("art.jpg", test_files[i].use_folder)).Get(); + std::string compare = CURL(test_files[i].base).Get(); + EXPECT_EQ(path, compare); + } + + for (unsigned int i = 0; i < sizeof(test_file2) / sizeof(testfiles); i++) + { + CFileItem item; + item.SetPath(test_file2[i].file); + std::string path = CURL(item.GetLocalArt("", test_file2[i].use_folder)).Get(); + std::string compare = CURL(test_file2[i].base).Get(); + EXPECT_EQ(path, compare); + } +} + +TEST(TestFileItem, GetBaseMoviePath) +{ + typedef struct + { + const char *file; + bool use_folder; + const char *base; + } testfiles; + + const testfiles test_files[] = {{ "c:\\dir\\filename.avi", false, "c:\\dir\\filename.avi" }, + { "c:\\dir\\filename.avi", true, "c:\\dir\\" }, + { "/dir/filename.avi", false, "/dir/filename.avi" }, + { "/dir/filename.avi", true, "/dir/" }, + { "smb://somepath/file.avi", false, "smb://somepath/file.avi" }, + { "smb://somepath/file.avi", true, "smb://somepath/" }, + { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", false, "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi" }, + { "stack:///path/to/movie_name/cd1/some_file1.avi , /path/to/movie_name/cd2/some_file2.avi", true, "/path/to/movie_name/" }, + { "/home/user/TV Shows/Dexter/S1/1x01.avi", false, "/home/user/TV Shows/Dexter/S1/1x01.avi" }, + { "/home/user/TV Shows/Dexter/S1/1x01.avi", true, "/home/user/TV Shows/Dexter/S1/" }, + { "rar://g%3a%5cmultimedia%5cmovies%5cSphere%2erar/Sphere.avi", true, "g:\\multimedia\\movies\\" }, + { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", false, "/home/user/movies/movie_name/" }, + { "/home/user/movies/movie_name/video_ts/VIDEO_TS.IFO", true, "/home/user/movies/movie_name/" }, + { "/home/user/movies/movie_name/BDMV/index.bdmv", false, "/home/user/movies/movie_name/" }, + { "/home/user/movies/movie_name/BDMV/index.bdmv", true, "/home/user/movies/movie_name/" }}; + + for (unsigned int i = 0; i < sizeof(test_files) / sizeof(testfiles); i++) + { + CFileItem item; + item.SetPath(test_files[i].file); + std::string path = CURL(item.GetBaseMoviePath(test_files[i].use_folder)).Get(); + std::string compare = CURL(test_files[i].base).Get(); + EXPECT_EQ(path, compare); + } +} diff --git a/xbmc/utils/Archive.cpp b/xbmc/utils/Archive.cpp index c0d0fcffbe..4feaf04443 100644 --- a/xbmc/utils/Archive.cpp +++ b/xbmc/utils/Archive.cpp @@ -155,6 +155,30 @@ CArchive& CArchive::operator<<(char c) return *this; } +CArchive& CArchive::operator<<(const std::string& str) +{ + *this << (int)str.size(); + + int size = str.size(); + if (m_BufferPos + size >= BUFFER_MAX) + FlushBuffer(); + + int iBufferMaxParts=size/BUFFER_MAX; + for (int i=0; i<iBufferMaxParts; i++) + { + memcpy(&m_pBuffer[m_BufferPos], str.c_str()+(i*BUFFER_MAX), BUFFER_MAX); + m_BufferPos+=BUFFER_MAX; + FlushBuffer(); + } + + int iPos=iBufferMaxParts*BUFFER_MAX; + int iSizeLeft=size-iPos; + memcpy(&m_pBuffer[m_BufferPos], str.c_str()+iPos, iSizeLeft); + m_BufferPos+=iSizeLeft; + + return *this; +} + CArchive& CArchive::operator<<(const CStdString& str) { *this << str.GetLength(); @@ -237,7 +261,7 @@ CArchive& CArchive::operator<<(const CVariant& variant) *this << variant.asBoolean(); break; case CVariant::VariantTypeString: - *this << CStdString(variant.asString()); + *this << variant.asString(); break; case CVariant::VariantTypeDouble: *this << variant.asDouble(); @@ -251,7 +275,7 @@ CArchive& CArchive::operator<<(const CVariant& variant) *this << variant.size(); for (CVariant::const_iterator_map itr = variant.begin_map(); itr != variant.end_map(); itr++) { - *this << CStdString(itr->first); + *this << itr->first; *this << itr->second; } break; @@ -268,7 +292,7 @@ CArchive& CArchive::operator<<(const std::vector<std::string>& strArray) { *this << (unsigned int)strArray.size(); for (unsigned int index = 0; index < strArray.size(); index++) - *this << CStdString(strArray.at(index)); + *this << strArray.at(index); return *this; } @@ -338,6 +362,19 @@ CArchive& CArchive::operator>>(char& c) return *this; } +CArchive& CArchive::operator>>(std::string& str) +{ + int iLength = 0; + *this >> iLength; + + char *s = new char[iLength]; + m_pFile->Read(s, iLength); + str.assign(s, iLength); + delete[] s; + + return *this; +} + CArchive& CArchive::operator>>(CStdString& str) { int iLength = 0; @@ -407,7 +444,7 @@ CArchive& CArchive::operator>>(CVariant& variant) } case CVariant::VariantTypeString: { - CStdString value; + std::string value; *this >> value; variant = value; break; @@ -437,7 +474,7 @@ CArchive& CArchive::operator>>(CVariant& variant) *this >> size; for (; size > 0; size--) { - CStdString name; + std::string name; CVariant value; *this >> name; *this >> value; @@ -461,7 +498,7 @@ CArchive& CArchive::operator>>(std::vector<std::string>& strArray) strArray.clear(); for (int index = 0; index < size; index++) { - CStdString str; + std::string str; *this >> str; strArray.push_back(str); } diff --git a/xbmc/utils/Archive.h b/xbmc/utils/Archive.h index 4c69b99952..a78362547e 100644 --- a/xbmc/utils/Archive.h +++ b/xbmc/utils/Archive.h @@ -52,6 +52,7 @@ public: CArchive& operator<<(uint64_t ui64); CArchive& operator<<(bool b); CArchive& operator<<(char c); + CArchive& operator<<(const std::string &str); CArchive& operator<<(const CStdString& str); CArchive& operator<<(const CStdStringW& str); CArchive& operator<<(const SYSTEMTIME& time); @@ -69,6 +70,7 @@ public: CArchive& operator>>(uint64_t& ui64); CArchive& operator>>(bool& b); CArchive& operator>>(char& c); + CArchive& operator>>(std::string &str); CArchive& operator>>(CStdString& str); CArchive& operator>>(CStdStringW& str); CArchive& operator>>(SYSTEMTIME& time); diff --git a/xbmc/utils/RecentlyAddedJob.cpp b/xbmc/utils/RecentlyAddedJob.cpp index edcf6b9a09..07ed917846 100644 --- a/xbmc/utils/RecentlyAddedJob.cpp +++ b/xbmc/utils/RecentlyAddedJob.cpp @@ -73,11 +73,11 @@ bool CRecentlyAddedJob::UpdateVideo() home->SetProperty("LatestMovie." + value + ".Path" , item->GetVideoInfoTag()->m_strFileNameAndPath); home->SetProperty("LatestMovie." + value + ".Trailer" , item->GetVideoInfoTag()->m_strTrailer); - if (!item->HasThumbnail()) + if (!item->HasArt("thumb")) m_thumbLoader.LoadItem(item.get()); - home->SetProperty("LatestMovie." + value + ".Thumb" , item->GetThumbnailImage()); - home->SetProperty("LatestMovie." + value + ".Fanart" , item->GetProperty("fanart_image")); + home->SetProperty("LatestMovie." + value + ".Thumb" , item->GetArt("thumb")); + home->SetProperty("LatestMovie." + value + ".Fanart" , item->GetArt("fanart")); } } for (; i < NUM_ITEMS; ++i) @@ -123,17 +123,17 @@ bool CRecentlyAddedJob::UpdateVideo() home->SetProperty("LatestEpisode." + value + ".EpisodeNumber" , EpisodeNumber); home->SetProperty("LatestEpisode." + value + ".Path" , item->GetVideoInfoTag()->m_strFileNameAndPath); - if (!item->HasThumbnail()) + if (!item->HasArt("thumb")) m_thumbLoader.LoadItem(item.get()); std::string seasonThumb; if (item->GetVideoInfoTag()->m_iIdSeason > 0) seasonThumb = videodatabase.GetArtForItem(item->GetVideoInfoTag()->m_iIdSeason, "season", "thumb"); - home->SetProperty("LatestEpisode." + value + ".Thumb" , item->GetThumbnailImage()); - home->SetProperty("LatestEpisode." + value + ".ShowThumb" , item->GetProperty("tvshowthumb")); + home->SetProperty("LatestEpisode." + value + ".Thumb" , item->GetArt("thumb")); + home->SetProperty("LatestEpisode." + value + ".ShowThumb" , item->GetArt("tvshowthumb")); home->SetProperty("LatestEpisode." + value + ".SeasonThumb" , seasonThumb); - home->SetProperty("LatestEpisode." + value + ".Fanart" , item->GetProperty("fanart_image")); + home->SetProperty("LatestEpisode." + value + ".Fanart" , item->GetArt("fanart")); } } for (; i < NUM_ITEMS; ++i) @@ -172,11 +172,11 @@ bool CRecentlyAddedJob::UpdateVideo() home->SetProperty("LatestMusicVideo." + value + ".Path" , item->GetVideoInfoTag()->m_strFileNameAndPath); home->SetProperty("LatestMusicVideo." + value + ".Artist" , StringUtils::Join(item->GetVideoInfoTag()->m_artist, g_advancedSettings.m_videoItemSeparator)); - if (!item->HasThumbnail()) + if (!item->HasArt("thumb")) m_thumbLoader.LoadItem(item.get()); - home->SetProperty("LatestMusicVideo." + value + ".Thumb" , item->GetThumbnailImage()); - home->SetProperty("LatestMusicVideo." + value + ".Fanart" , item->GetProperty("fanart_image")); + home->SetProperty("LatestMusicVideo." + value + ".Thumb" , item->GetArt("thumb")); + home->SetProperty("LatestMusicVideo." + value + ".Fanart" , item->GetArt("fanart")); } } for (; i < NUM_ITEMS; ++i) @@ -236,8 +236,8 @@ bool CRecentlyAddedJob::UpdateMusic() if (loader.LoadItem(item.get())) { - strAlbumThumb = item->GetThumbnailImage(); - strAlbumFanart = item->GetProperty("fanart_image").asString(); + strAlbumThumb = item->GetArt("thumb"); + strAlbumFanart = item->GetArt("fanart"); } } diff --git a/xbmc/utils/ScraperUrl.cpp b/xbmc/utils/ScraperUrl.cpp index 58be860e68..f1b55cf736 100644 --- a/xbmc/utils/ScraperUrl.cpp +++ b/xbmc/utils/ScraperUrl.cpp @@ -107,6 +107,9 @@ bool CScraperUrl::ParseElement(const TiXmlElement* element) if (szSeason) url.m_season = atoi(szSeason); } + const char *aspect = element->Attribute("aspect"); + if (aspect) + url.m_aspect = aspect; m_url.push_back(url); @@ -149,11 +152,11 @@ bool CScraperUrl::ParseString(CStdString strUrl) return true; } -const CScraperUrl::SUrlEntry CScraperUrl::GetFirstThumb() const +const CScraperUrl::SUrlEntry CScraperUrl::GetFirstThumb(const std::string &type) const { for (vector<SUrlEntry>::const_iterator iter=m_url.begin();iter != m_url.end();++iter) { - if (iter->m_type == URL_TYPE_GENERAL) + if (iter->m_type == URL_TYPE_GENERAL && (type.empty() || type == "thumb" || iter->m_aspect == type)) return *iter; } @@ -303,14 +306,17 @@ CStdString CScraperUrl::GetThumbURL(const CScraperUrl::SUrlEntry &entry) return entry.m_url + "|Referer=" + spoof; } -void CScraperUrl::GetThumbURLs(std::vector<CStdString> &thumbs, int season) const +void CScraperUrl::GetThumbURLs(std::vector<CStdString> &thumbs, const std::string &type, int season) const { for (vector<SUrlEntry>::const_iterator iter = m_url.begin(); iter != m_url.end(); ++iter) { - if ((iter->m_type == CScraperUrl::URL_TYPE_GENERAL && season == -1) - || (iter->m_type == CScraperUrl::URL_TYPE_SEASON && iter->m_season == season)) + if (iter->m_aspect == type || type.empty() || type == "thumb") { - thumbs.push_back(GetThumbURL(*iter)); + if ((iter->m_type == CScraperUrl::URL_TYPE_GENERAL && season == -1) + || (iter->m_type == CScraperUrl::URL_TYPE_SEASON && iter->m_season == season)) + { + thumbs.push_back(GetThumbURL(*iter)); + } } } } diff --git a/xbmc/utils/ScraperUrl.h b/xbmc/utils/ScraperUrl.h index 0b417e1d59..e414f89285 100644 --- a/xbmc/utils/ScraperUrl.h +++ b/xbmc/utils/ScraperUrl.h @@ -47,6 +47,7 @@ public: CStdString m_spoof; CStdString m_url; CStdString m_cache; + std::string m_aspect; URLTYPES m_type; bool m_post; bool m_isgz; @@ -58,8 +59,8 @@ public: bool ParseElement(const TiXmlElement*); bool ParseEpisodeGuide(CStdString strUrls); // copies by intention - const SUrlEntry GetFirstThumb() const; - const SUrlEntry GetSeasonThumb(int) const; + const SUrlEntry GetFirstThumb(const std::string &type = "") const; + const SUrlEntry GetSeasonThumb(int season) const; void GetSeasonThumbs(std::map<int, std::string> &thumbs) const; /*! \brief fetch the full URL (including referrer) of a thumb @@ -70,9 +71,10 @@ public: /*! \brief fetch the full URL (including referrer) of thumbs \param thumbs [out] vector of thumb URLs to fill + \param type the type of thumb URLs to fetch, if empty (the default) picks any \param season number of season that we want thumbs for, -1 indicates no season (the default) */ - void GetThumbURLs(std::vector<CStdString> &thumbs, int season = -1) const; + void GetThumbURLs(std::vector<CStdString> &thumbs, const std::string &type = "", int season = -1) const; void Clear(); static bool Get(const SUrlEntry&, std::string&, XFILE::CCurlFile& http, const CStdString& cacheContext); diff --git a/xbmc/utils/TuxBoxUtil.cpp b/xbmc/utils/TuxBoxUtil.cpp index 79ff6487bb..c0676555e3 100644 --- a/xbmc/utils/TuxBoxUtil.cpp +++ b/xbmc/utils/TuxBoxUtil.cpp @@ -138,7 +138,7 @@ bool CTuxBoxUtil::CreateNewItem(const CFileItem& item, CFileItem& item_new) //Build new Item item_new.SetLabel(item.GetLabel()); item_new.SetPath(item.GetPath()); - item_new.SetThumbnailImage(item.GetThumbnailImage()); + item_new.SetArt("thumb", item.GetArt("thumb")); if(g_tuxbox.GetZapUrl(item.GetPath(), item_new)) { @@ -320,7 +320,7 @@ bool CTuxBoxUtil::ParseChannels(TiXmlElement *root, CFileItemList &items, CURL & pbItem->SetLabel(strItemName); pbItem->SetLabelPreformated(true); pbItem->SetPath("tuxbox://"+url.GetUserName()+":"+url.GetPassWord()+"@"+url.GetHostName()+strPort+"/cgi-bin/zapTo?path="+strItemPath+".ts"); - pbItem->SetThumbnailImage(GetPicon(strItemName)); //Set Picon Image + pbItem->SetArt("thumb", GetPicon(strItemName)); //Set Picon Image //DEBUG Log CLog::Log(LOGDEBUG, "%s - Name: %s", __FUNCTION__,strItemName.c_str()); diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp index 5419f0da29..706c2371a2 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -954,6 +954,13 @@ void URIUtils::AddFileToFolder(const CStdString& strFolder, strResult.Replace('/', '\\'); } +CStdString URIUtils::GetDirectory(const CStdString &filePath) +{ + CStdString directory; + GetDirectory(filePath, directory); + return directory; +} + void URIUtils::GetDirectory(const CStdString& strFilePath, CStdString& strDirectoryPath) { diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h index 75a2f6ad18..56b43d6640 100644 --- a/xbmc/utils/URIUtils.h +++ b/xbmc/utils/URIUtils.h @@ -34,6 +34,8 @@ public: static void GetDirectory(const CStdString& strFilePath, CStdString& strDirectoryPath); + static CStdString GetDirectory(const CStdString &filePath); + static const CStdString GetExtension(const CStdString& strFileName); static void GetExtension(const CStdString& strFile, CStdString& strExtension); static const CStdString GetFileName(const CStdString& strFileNameAndPath); diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp index 7964e966cd..4eba8803af 100644 --- a/xbmc/video/VideoDatabase.cpp +++ b/xbmc/video/VideoDatabase.cpp @@ -5949,7 +5949,7 @@ void CVideoDatabase::Stack(CFileItemList& items, VIDEODB_CONTENT_TYPE type, bool { CFileItemPtr pItem = items.Get(i); CStdString strTitle = pItem->GetVideoInfoTag()->m_strTitle; - CStdString strFanArt = pItem->GetProperty("fanart_image").asString(); + CStdString strFanArt = pItem->GetArt("fanart"); int j = i + 1; bool bStacked = false; @@ -5977,7 +5977,7 @@ void CVideoDatabase::Stack(CFileItemList& items, VIDEODB_CONTENT_TYPE type, bool // check for fanart if not already set if (strFanArt.IsEmpty()) - strFanArt = jItem->GetProperty("fanart_image").asString(); + strFanArt = jItem->GetArt("fanart"); // remove duplicate entry items.Remove(j); @@ -5992,7 +5992,7 @@ void CVideoDatabase::Stack(CFileItemList& items, VIDEODB_CONTENT_TYPE type, bool pItem->GetVideoInfoTag()->m_playCount = (pItem->GetVideoInfoTag()->m_iEpisode == (int)pItem->GetProperty("watchedepisodes").asInteger()) ? 1 : 0; pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, (pItem->GetVideoInfoTag()->m_playCount > 0) && (pItem->GetVideoInfoTag()->m_iEpisode > 0)); if (!strFanArt.IsEmpty()) - pItem->SetProperty("fanart_image", strFanArt); + pItem->SetArt("fanart", strFanArt); } // increment i to j which is the next item i = j; @@ -6014,7 +6014,7 @@ void CVideoDatabase::Stack(CFileItemList& items, VIDEODB_CONTENT_TYPE type, bool CStdString strPath = pItem->GetVideoInfoTag()->m_strPath; int iSeason = pItem->GetVideoInfoTag()->m_iSeason; int iEpisode = pItem->GetVideoInfoTag()->m_iEpisode; - //CStdString strFanArt = pItem->GetProperty("fanart_image"); + //CStdString strFanArt = pItem->GetArt("fanart"); // do we have a dvd folder, ie foo/VIDEO_TS.IFO or foo/VIDEO_TS/VIDEO_TS.IFO CStdString strFileNameAndPath = pItem->GetVideoInfoTag()->m_strFileNameAndPath; @@ -6059,7 +6059,7 @@ void CVideoDatabase::Stack(CFileItemList& items, VIDEODB_CONTENT_TYPE type, bool // episodes dont have fanart yet //if (strFanArt.IsEmpty()) - // strFanArt = jItem->GetProperty("fanart_image"); + // strFanArt = jItem->GetArt("fanart"); paths.push_back(jFileNameAndPath); } @@ -6085,7 +6085,7 @@ void CVideoDatabase::Stack(CFileItemList& items, VIDEODB_CONTENT_TYPE type, bool // episodes dont have fanart yet //if (!strFanArt.IsEmpty()) - // pItem->SetProperty("fanart_image", strFanArt); + // pItem->SetArt("fanart", strFanArt); } // increment i to j which is the next item i = j; @@ -8143,8 +8143,6 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f } CFileItem item(movie.m_strFileNameAndPath,false); - CFileItem saveItem(item); - saveItem.SetArt(artwork); if (singleFiles && CUtil::SupportsFileOperations(movie.m_strFileNameAndPath)) { if (!item.Exists(false)) @@ -8187,14 +8185,11 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f if (singleFiles && images && !bSkip) { - CStdString savedThumb(saveItem.GetTBNFile()); - if (saveItem.HasThumbnail() && (overwrite || !CFile::Exists(savedThumb, false))) - CTextureCache::Get().Export(saveItem.GetThumbnailImage(), savedThumb); - - CStdString savedFanart(URIUtils::ReplaceExtension(savedThumb, "-fanart.jpg")); - if (saveItem.HasProperty("fanart_image") && (overwrite || !CFile::Exists(savedFanart, false))) - CTextureCache::Get().Export(saveItem.GetProperty("fanart_image").asString(), savedFanart); - + for (map<string, string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i) + { + CStdString savedThumb = item.GetLocalArt(i->first, false); + CTextureCache::Get().Export(i->second, savedThumb, overwrite); + } if (actorThumbs) ExportActorThumbs(actorsDir, movie, singleFiles, overwrite); } @@ -8242,8 +8237,6 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f } CFileItem item(movie.m_strFileNameAndPath,false); - CFileItem saveItem(item); - saveItem.SetArt(artwork); if (CUtil::SupportsFileOperations(movie.m_strFileNameAndPath) && singleFiles) { if (!item.Exists(false)) @@ -8280,9 +8273,11 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f } if (singleFiles && images && !bSkip) { - CStdString savedThumb(saveItem.GetTBNFile()); - if (saveItem.HasThumbnail() && (overwrite || !CFile::Exists(savedThumb, false))) - CTextureCache::Get().Export(saveItem.GetThumbnailImage(), savedThumb); + for (map<string, string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i) + { + CStdString savedThumb = item.GetLocalArt(i->first, false); + CTextureCache::Get().Export(i->second, savedThumb, overwrite); + } } m_pDS->next(); current++; @@ -8339,8 +8334,6 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f CFileItem item(tvshow.m_strPath, true); - CFileItem saveItem(item); - saveItem.SetArt(artwork); if (singleFiles && CUtil::SupportsFileOperations(tvshow.m_strPath)) { if (!item.Exists(false)) @@ -8378,13 +8371,11 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f } if (singleFiles && images && !bSkip) { - CStdString savedThumb(saveItem.GetFolderThumb()); - if (saveItem.HasThumbnail() && (overwrite || !CFile::Exists(savedThumb, false))) - CTextureCache::Get().Export(saveItem.GetThumbnailImage(), savedThumb); - - CStdString savedFanart(saveItem.GetFolderThumb("fanart.jpg")); - if (saveItem.HasProperty("fanart_image") && (overwrite || !CFile::Exists(savedFanart, false))) - CTextureCache::Get().Export(saveItem.GetProperty("fanart_image").asString(), savedFanart); + for (map<string, string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i) + { + CStdString savedThumb = item.GetLocalArt(i->first, true); + CTextureCache::Get().Export(i->second, savedThumb, overwrite); + } if (actorThumbs) ExportActorThumbs(actorsDir, tvshow, singleFiles, overwrite); @@ -8394,21 +8385,21 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f { CStdString seasonThumb; if (i->first == -1) - seasonThumb = "season-all.tbn"; + seasonThumb = "season-all"; else if (i->first == 0) - seasonThumb = "season-specials.tbn"; + seasonThumb = "season-specials"; else - seasonThumb.Format("season%02i.tbn", i->first); - CStdString savedThumb(saveItem.GetFolderThumb(seasonThumb)); - if (!i->second.empty() && (overwrite || !CFile::Exists(savedThumb, false))) - CTextureCache::Get().Export(i->second, savedThumb); + seasonThumb.Format("season%02i", i->first); + CStdString savedThumb(item.GetLocalArt(seasonThumb, true)); + if (!i->second.empty()) + CTextureCache::Get().Export(i->second, savedThumb, overwrite); } } // now save the episodes from this show sql = PrepareSQL("select * from episodeview where idShow=%i order by strFileName, idEpisode",tvshow.m_iDbId); pDS->query(sql.c_str()); - CStdString showDir(saveItem.GetPath()); + CStdString showDir(item.GetPath()); while (!pDS->eof()) { @@ -8439,8 +8430,6 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f bool bSkip = false; CFileItem item(episode.m_strFileNameAndPath, false); - CFileItem saveItem(item); - saveItem.SetArt(artwork); if (singleFiles) { if (!item.Exists(false)) @@ -8478,10 +8467,11 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f if (singleFiles && images && !bSkip) { - CStdString savedThumb(saveItem.GetTBNFile()); - if (saveItem.HasThumbnail() && (overwrite || !CFile::Exists(savedThumb, false))) - CTextureCache::Get().Export(saveItem.GetThumbnailImage(), savedThumb); - + for (map<string, string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i) + { + CStdString savedThumb = item.GetLocalArt(i->first, false); + CTextureCache::Get().Export(i->second, savedThumb, overwrite); + } if (actorThumbs) ExportActorThumbs(actorsDir, episode, singleFiles, overwrite); } @@ -8552,9 +8542,8 @@ void CVideoDatabase::ExportActorThumbs(const CStdString &strDir, const CVideoInf item.SetLabel(iter->strName); if (!iter->thumb.IsEmpty()) { - CStdString thumbFile(GetSafeFile(strPath, iter->strName) + ".tbn"); - if (overwrite || !CFile::Exists(thumbFile)) - CTextureCache::Get().Export(iter->thumb, thumbFile); + CStdString thumbFile(GetSafeFile(strPath, iter->strName)); + CTextureCache::Get().Export(iter->thumb, thumbFile, overwrite); } } } diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp index 8e5ac589e4..6076fbb2f6 100644 --- a/xbmc/video/VideoInfoScanner.cpp +++ b/xbmc/video/VideoInfoScanner.cpp @@ -1144,56 +1144,80 @@ namespace VIDEO return lResult; } + string ContentToMediaType(CONTENT_TYPE content, bool folder) + { + switch (content) + { + case CONTENT_MOVIES: + return "movie"; + case CONTENT_MUSICVIDEOS: + return "musicvideo"; + case CONTENT_TVSHOWS: + return folder ? "tvshow" : "episode"; + default: + return ""; + } + } + void CVideoInfoScanner::GetArtwork(CFileItem *pItem, const CONTENT_TYPE &content, bool bApplyToDir, bool useLocal) { CVideoInfoTag &movieDetails = *pItem->GetVideoInfoTag(); movieDetails.m_fanart.Unpack(); movieDetails.m_strPictureURL.Parse(); - // get & save fanart image + CGUIListItem::ArtMap art; + // get & save fanart image (treated separately due to it being stored in m_fanart) bool isEpisode = (content == CONTENT_TVSHOWS && !pItem->m_bIsFolder); if (!isEpisode) { - CStdString fanart; - if (pItem->HasProperty("fanart_image")) - fanart = pItem->GetProperty("fanart_image").asString(); - else if (useLocal) - fanart = pItem->GetLocalFanart(); + CStdString fanart = pItem->GetArt("fanart"); + if (fanart.empty() && useLocal) + fanart = pItem->FindLocalArt("fanart.jpg", true); if (fanart.IsEmpty()) fanart = movieDetails.m_fanart.GetImageURL(); if (!fanart.IsEmpty()) - { - CTextureCache::Get().BackgroundCacheImage(fanart); - pItem->SetProperty("fanart_image", fanart); - } + art.insert(make_pair("fanart", fanart)); } - // get and cache thumb image - CStdString thumb; - if (pItem->HasThumbnail()) - thumb = pItem->GetThumbnailImage(); - else if (useLocal) + // get and cache thumb images + vector<string> artTypes = CVideoThumbLoader::GetArtTypes(ContentToMediaType(content, pItem->m_bIsFolder)); + for (vector<string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i) { - thumb = pItem->GetUserVideoThumb(); - if (bApplyToDir && thumb.IsEmpty()) - { - CStdString strParent; - URIUtils::GetParentPath(pItem->GetPath(), strParent); - CFileItem folderItem(*pItem); - folderItem.SetPath(strParent); - folderItem.m_bIsFolder = true; - thumb = folderItem.GetUserVideoThumb(); - } + string type = *i; + if (type == "fanart") + continue; // handled above + std::string image = GetImage(pItem, useLocal, bApplyToDir, type); + if (!image.empty()) + art.insert(make_pair(type, image)); } - if (thumb.IsEmpty()) + for (CGUIListItem::ArtMap::const_iterator i = art.begin(); i != art.end(); ++i) + CTextureCache::Get().BackgroundCacheImage(i->second); + + pItem->SetArt(art); + + // parent folder to apply the thumb to and to search for local actor thumbs + CStdString parentDir = GetParentDir(*pItem); + if (g_guiSettings.GetBool("videolibrary.actorthumbs")) + FetchActorThumbs(movieDetails.m_cast, parentDir); + if (bApplyToDir) + ApplyThumbToFolder(parentDir, art["thumb"]); + } + + std::string CVideoInfoScanner::GetImage(CFileItem *pItem, bool useLocal, bool bApplyToDir, const std::string &type) + { + std::string thumb; + if (useLocal) + thumb = CVideoThumbLoader::GetLocalArt(*pItem, type, bApplyToDir); + + if (thumb.empty()) { - thumb = CScraperUrl::GetThumbURL(movieDetails.m_strPictureURL.GetFirstThumb()); - if (!thumb.IsEmpty()) + thumb = CScraperUrl::GetThumbURL(pItem->GetVideoInfoTag()->m_strPictureURL.GetFirstThumb(type)); + if (!thumb.empty()) { - if (thumb.Find("http://") < 0 && - thumb.Find("/") < 0 && - thumb.Find("\\") < 0) + if (thumb.find("http://") == string::npos && + thumb.find("/") == string::npos && + thumb.find("\\") == string::npos) { CStdString strPath; URIUtils::GetDirectory(pItem->GetPath(), strPath); @@ -1201,18 +1225,7 @@ namespace VIDEO } } } - if (!thumb.IsEmpty()) - { - CTextureCache::Get().BackgroundCacheImage(thumb); - pItem->SetThumbnailImage(thumb); - } - - // parent folder to apply the thumb to and to search for local actor thumbs - CStdString parentDir = GetParentDir(*pItem); - if (g_guiSettings.GetBool("videolibrary.actorthumbs")) - FetchActorThumbs(movieDetails.m_cast, parentDir); - if (bApplyToDir) - ApplyThumbToFolder(parentDir, thumb); + return thumb; } INFO_RET CVideoInfoScanner::OnProcessSeriesFolder(EPISODELIST& files, const ADDON::ScraperPtr &scraper, bool useLocal, int idShow, const CStdString& strShowTitle, CGUIDialogProgress* pDlgProgress /* = NULL */) @@ -1603,18 +1616,18 @@ namespace VIDEO if (useLocal) { CFileItemList items; - CDirectory::GetDirectory(show.m_strPath, items, ".tbn"); + CDirectory::GetDirectory(show.m_strPath, items, ".png|.jpg|.tbn", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_NO_FILE_INFO); // run through all these items and see which ones match CRegExp reg; - if (items.Size() && reg.RegComp("season[ ._-]?([0-9]+)\\.tbn")) + if (items.Size() && reg.RegComp("season[ ._-]?([0-9]+)\\.(tbn|jpg|png)")) { for (int i = 0; i < items.Size(); i++) { CStdString name = URIUtils::GetFileName(items[i]->GetPath()); - name.ToLower(); - if (name == "season-all.tbn") + URIUtils::RemoveExtension(name); + if (name == "season-all") art.insert(make_pair(-1, items[i]->GetPath())); - else if (name == "season-specials.tbn") + else if (name == "season-specials") art.insert(make_pair(0, items[i]->GetPath())); else if (reg.RegFind(name) > -1) { @@ -1634,17 +1647,25 @@ namespace VIDEO void CVideoInfoScanner::FetchActorThumbs(vector<SActorInfo>& actors, const CStdString& strPath) { + CFileItemList items; + CDirectory::GetDirectory(URIUtils::AddFileToFolder(strPath, ".actors"), items, ".png|.jpg|.tbn", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_NO_FILE_INFO); for (vector<SActorInfo>::iterator i = actors.begin(); i != actors.end(); ++i) { if (i->thumb.IsEmpty()) { CStdString thumbFile = i->strName; thumbFile.Replace(" ","_"); - thumbFile += ".tbn"; - CStdString strLocal = URIUtils::AddFileToFolder(URIUtils::AddFileToFolder(strPath, ".actors"), thumbFile); - if (CFile::Exists(strLocal)) - i->thumb = strLocal; - else if (!i->thumbUrl.GetFirstThumb().m_url.IsEmpty()) + for (int j = 0; j < items.Size(); j++) + { + CStdString compare = URIUtils::GetFileName(items[j]->GetPath()); + URIUtils::RemoveExtension(compare); + if (!items[j]->m_bIsFolder && compare == thumbFile) + { + i->thumb = compare; + break; + } + } + if (i->thumb.IsEmpty() && !i->thumbUrl.GetFirstThumb().m_url.IsEmpty()) i->thumb = CScraperUrl::GetThumbURL(i->thumbUrl.GetFirstThumb()); if (!i->thumb.IsEmpty()) CTextureCache::Get().BackgroundCacheImage(i->thumb); diff --git a/xbmc/video/VideoInfoScanner.h b/xbmc/video/VideoInfoScanner.h index f3e3068d9e..558c82f336 100644 --- a/xbmc/video/VideoInfoScanner.h +++ b/xbmc/video/VideoInfoScanner.h @@ -106,6 +106,7 @@ namespace VIDEO \param useLocal whether to use local thumbs, defaults to true */ static void GetSeasonThumbs(const CVideoInfoTag &show, std::map<int, std::string> &art, bool useLocal = true); + static std::string GetImage(CFileItem *pItem, bool useLocal, bool bApplyToDir, const std::string &type = ""); protected: virtual void Process(); diff --git a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp index a23d156a8b..e173ad0591 100644 --- a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp @@ -194,7 +194,7 @@ void CGUIDialogVideoBookmarks::Update() bookmarkTime = StringUtils::SecondsToTimeString((long)m_bookmarks[i].timeInSeconds, TIME_FORMAT_HH_MM_SS); CFileItemPtr item(new CFileItem(bookmarkTime)); - item->SetThumbnailImage(m_bookmarks[i].thumbNailImage); + item->SetArt("thumb", m_bookmarks[i].thumbNailImage); m_vecItems->Add(item); } m_viewControl.SetItems(*m_vecItems); diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp index 5d03dcb58c..bbec3a5eb3 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp @@ -167,7 +167,7 @@ bool CGUIDialogVideoInfo::OnMessage(CGUIMessage& message) } else if (iControl == CONTROL_BTN_GET_THUMB) { - OnGetThumb(); + OnGetArt(); } else if (iControl == CONTROL_BTN_PLAY_TRAILER) { @@ -211,8 +211,8 @@ bool CGUIDialogVideoInfo::OnMessage(CGUIMessage& message) CFileItemPtr item = boost::static_pointer_cast<CFileItem>(message.GetItem()); if (item && m_movieItem->GetPath().Equals(item->GetPath())) { // Just copy over the stream details and the thumb if we don't already have one - if (!m_movieItem->HasThumbnail()) - m_movieItem->SetThumbnailImage(item->GetThumbnailImage()); + if (!m_movieItem->HasArt("thumb")) + m_movieItem->SetArt("thumb", item->GetArt("thumb")); m_movieItem->GetVideoInfoTag()->m_streamDetails = item->GetVideoInfoTag()->m_streamDetails; } return true; @@ -243,7 +243,7 @@ void CGUIDialogVideoInfo::SetMovie(const CFileItem *item) CStdString thumb = database.GetArtForItem(idArtist, "artist", "thumb"); CFileItemPtr item(new CFileItem(*it)); if (!thumb.empty()) - item->SetThumbnailImage(thumb); + item->SetArt("thumb", thumb); item->SetIconImage("DefaultArtist.png"); m_castList->Add(item); } @@ -260,13 +260,13 @@ void CGUIDialogVideoInfo::SetMovie(const CFileItem *item) character.Format("%s %s %s", it->strName.c_str(), g_localizeStrings.Get(20347).c_str(), it->strRole.c_str()); CFileItemPtr item(new CFileItem(it->strName)); if (!it->thumb.IsEmpty()) - item->SetThumbnailImage(it->thumb); + item->SetArt("thumb", it->thumb); else if (g_guiSettings.GetBool("videolibrary.actorthumbs")) { // backward compatibility CStdString thumb = CScraperUrl::GetThumbURL(it->thumbUrl.GetFirstThumb()); if (!thumb.IsEmpty()) { - item->SetThumbnailImage(thumb); + item->SetArt("thumb", thumb); CTextureCache::Get().BackgroundCacheImage(thumb); } } @@ -308,7 +308,7 @@ void CGUIDialogVideoInfo::SetMovie(const CFileItem *item) m_movieItem->GetVideoInfoTag()->m_iSeason); string thumb = db.GetArtForItem(seasonID, "season", "thumb"); if (!thumb.empty()) - m_movieItem->SetProperty("seasonthumb", thumb); + m_movieItem->SetArt("seasonthumb", thumb); } db.Close(); } @@ -395,7 +395,7 @@ void CGUIDialogVideoInfo::Update() { CGUIImage* pImageControl = (CGUIImage*)pControl; pImageControl->FreeResources(); - pImageControl->SetFileName(m_movieItem->GetThumbnailImage()); + pImageControl->SetFileName(m_movieItem->GetArt("thumb")); } // tell our GUI to completely reload all controls (as some of them // are likely to have had this image in use so will need refreshing) @@ -587,43 +587,76 @@ void CGUIDialogVideoInfo::Play(bool resume) // 2. IMDb thumb // 3. Local thumb // 4. No thumb (if no Local thumb is available) -void CGUIDialogVideoInfo::OnGetThumb() +void CGUIDialogVideoInfo::OnGetArt() { + // prompt for choice + CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); + if (!dialog) + return; + CFileItemList items; + dialog->SetHeading(13511); + dialog->Reset(); + dialog->SetUseDetails(true); + + vector<string> artTypes = CVideoThumbLoader::GetArtTypes(m_movieItem->GetVideoInfoTag()->m_type); + for (vector<string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i) + { + string type = *i; + CFileItemPtr item(new CFileItem(type, "false")); + item->SetLabel(type); + if (m_movieItem->HasArt(type)) + item->SetArt("thumb", m_movieItem->GetArt(type)); + items.Add(item); + } + dialog->SetItems(&items); + dialog->DoModal(); + + string type = dialog->GetSelectedItem()->GetLabel(); + if (type.empty()) + return; // cancelled + + if (type == "fanart") + { // TODO: this can be removed once these are unified. + OnGetFanart(); + return; + } + + items.Clear(); // Current thumb - if (CFile::Exists(m_movieItem->GetThumbnailImage())) + if (CFile::Exists(m_movieItem->GetArt(type))) { CFileItemPtr item(new CFileItem("thumb://Current", false)); - item->SetThumbnailImage(m_movieItem->GetThumbnailImage()); - item->SetLabel(g_localizeStrings.Get(20016)); + item->SetArt("thumb", m_movieItem->GetArt(type)); + item->SetLabel(g_localizeStrings.Get(13512)); items.Add(item); } // Grab the thumbnails from the web vector<CStdString> thumbs; - m_movieItem->GetVideoInfoTag()->m_strPictureURL.GetThumbURLs(thumbs); + m_movieItem->GetVideoInfoTag()->m_strPictureURL.GetThumbURLs(thumbs, type); for (unsigned int i = 0; i < thumbs.size(); ++i) { CStdString strItemPath; strItemPath.Format("thumb://Remote%i", i); CFileItemPtr item(new CFileItem(strItemPath, false)); - item->SetThumbnailImage(thumbs[i]); + item->SetArt("thumb", thumbs[i]); item->SetIconImage("DefaultPicture.png"); - item->SetLabel(g_localizeStrings.Get(20015)); + item->SetLabel(g_localizeStrings.Get(13513)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } - CStdString localThumb(m_movieItem->GetUserVideoThumb()); - if (CFile::Exists(localThumb)) + CStdString localThumb = CVideoThumbLoader::GetLocalArt(*m_movieItem, type); + if (!localThumb.empty()) { CFileItemPtr item(new CFileItem("thumb://Local", false)); - item->SetThumbnailImage(localThumb); - item->SetLabel(g_localizeStrings.Get(20017)); + item->SetArt("thumb", localThumb); + item->SetLabel(g_localizeStrings.Get(13514)); items.Add(item); } else @@ -632,14 +665,14 @@ void CGUIDialogVideoInfo::OnGetThumb() // to delete the incorrect thumb CFileItemPtr item(new CFileItem("thumb://None", false)); item->SetIconImage("DefaultVideo.png"); - item->SetLabel(g_localizeStrings.Get(20018)); + item->SetLabel(g_localizeStrings.Get(13515)); items.Add(item); } CStdString result; VECSOURCES sources(g_settings.m_videoSources); g_mediaManager.GetLocalDrives(sources); - if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20019), result)) + if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(13511), result)) return; // user cancelled if (result == "thumb://Current") @@ -662,12 +695,12 @@ void CGUIDialogVideoInfo::OnGetThumb() CVideoDatabase db; if (db.Open()) { - db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, "thumb", newThumb); + db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, type, newThumb); db.Close(); } CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show - m_movieItem->SetThumbnailImage(newThumb); + m_movieItem->SetArt(type, newThumb); if (m_movieItem->HasProperty("set_folder_thumb")) { // have a folder thumb to set as well VIDEO::CVideoInfoScanner::ApplyThumbToFolder(m_movieItem->GetProperty("set_folder_thumb").asString(), newThumb); @@ -684,10 +717,10 @@ void CGUIDialogVideoInfo::OnGetFanart() CFileItemList items; CFileItem item(*m_movieItem->GetVideoInfoTag()); - if (item.HasProperty("fanart_image")) + if (item.HasArt("fanart")) { CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); - itemCurrent->SetThumbnailImage(item.GetProperty("fanart_image").asString()); + itemCurrent->SetArt("thumb", item.GetArt("fanart")); itemCurrent->SetLabel(g_localizeStrings.Get(20440)); items.Add(itemCurrent); } @@ -702,7 +735,7 @@ void CGUIDialogVideoInfo::OnGetFanart() strItemPath.Format("fanart://Remote%i",i); CFileItemPtr item(new CFileItem(strItemPath, false)); CStdString thumb = m_movieItem->GetVideoInfoTag()->m_fanart.GetPreviewURL(i); - item->SetThumbnailImage(CTextureCache::GetWrappedThumbURL(thumb)); + item->SetArt("thumb", CTextureCache::GetWrappedThumbURL(thumb)); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20441)); @@ -715,7 +748,7 @@ void CGUIDialogVideoInfo::OnGetFanart() if (!strLocal.IsEmpty()) { CFileItemPtr itemLocal(new CFileItem("fanart://Local",false)); - itemLocal->SetThumbnailImage(strLocal); + itemLocal->SetArt("thumb", strLocal); itemLocal->SetLabel(g_localizeStrings.Get(20438)); // TODO: Do we need to clear the cached image? @@ -767,10 +800,7 @@ void CGUIDialogVideoInfo::OnGetFanart() } CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show - if (!result.IsEmpty()) - m_movieItem->SetProperty("fanart_image", result); - else - m_movieItem->ClearProperty("fanart_image"); + m_movieItem->SetArt("fanart", result); m_hasUpdatedThumb = true; // Update our screen @@ -784,7 +814,7 @@ void CGUIDialogVideoInfo::PlayTrailer() *item.GetVideoInfoTag() = *m_movieItem->GetVideoInfoTag(); item.GetVideoInfoTag()->m_streamDetails.Reset(); item.GetVideoInfoTag()->m_strTitle.Format("%s (%s)",m_movieItem->GetVideoInfoTag()->m_strTitle.c_str(),g_localizeStrings.Get(20410)); - item.SetThumbnailImage(m_movieItem->GetThumbnailImage()); + item.SetArt("thumb", m_movieItem->GetArt("thumb")); item.GetVideoInfoTag()->m_iDbId = -1; item.GetVideoInfoTag()->m_iFileId = -1; @@ -809,7 +839,7 @@ void CGUIDialogVideoInfo::SetLabel(int iControl, const CStdString &strLabel) } } -const CStdString& CGUIDialogVideoInfo::GetThumbnail() const +std::string CGUIDialogVideoInfo::GetThumbnail() const { - return m_movieItem->GetThumbnailImage(); + return m_movieItem->GetArt("thumb"); } diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.h b/xbmc/video/dialogs/GUIDialogVideoInfo.h index 3851c4d86e..7cb6601e4a 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.h +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.h @@ -39,7 +39,7 @@ public: bool RefreshAll() const; bool HasUpdatedThumb() const { return m_hasUpdatedThumb; }; - const CStdString &GetThumbnail() const; + std::string GetThumbnail() const; virtual CFileItemPtr GetCurrentListItem(int offset = 0) { return m_movieItem; } const CFileItemList& CurrentDirectory() const { return *m_castList; }; virtual bool HasListItems() const { return true; }; @@ -53,7 +53,7 @@ protected: void DoSearch(CStdString& strSearch, CFileItemList& items); void OnSearchItemFound(const CFileItem* pItem); void Play(bool resume = false); - void OnGetThumb(); + void OnGetArt(); void OnGetFanart(); void PlayTrailer(); diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index 8759bd3733..7b3a72d608 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -586,8 +586,8 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const ScraperPtr &info2) // show dialog that we're downloading the movie info // clear artwork - item->SetThumbnailImage(""); - item->ClearProperty("fanart_image"); + item->SetArt("thumb", ""); + item->SetArt("fanart", ""); CFileItemList list; CStdString strPath=item->GetPath(); @@ -674,7 +674,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const ScraperPtr &info2) *item->GetVideoInfoTag() = movieDetails; pDlgInfo->SetMovie(item); pDlgInfo->DoModal(); - item->SetThumbnailImage(pDlgInfo->GetThumbnail()); + item->SetArt("thumb", pDlgInfo->GetThumbnail()); needsRefresh = pDlgInfo->NeedRefresh(); listNeedsUpdating = true; } diff --git a/xbmc/video/windows/GUIWindowVideoNav.cpp b/xbmc/video/windows/GUIWindowVideoNav.cpp index 638f788835..8e367338cd 100644 --- a/xbmc/video/windows/GUIWindowVideoNav.cpp +++ b/xbmc/video/windows/GUIWindowVideoNav.cpp @@ -280,7 +280,7 @@ bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemL dir.GetQueryParams(items.GetPath(),params); VIDEODATABASEDIRECTORY::NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath()); - items.SetThumbnailImage(""); + items.SetArt("thumb", ""); if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_EPISODES || node == NODE_TYPE_SEASONS || node == NODE_TYPE_RECENTLY_ADDED_EPISODES) @@ -293,9 +293,9 @@ bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemL if (m_database.GetArtForItem(details.m_iDbId, details.m_type, art)) { if (art.find("thumb") != art.end()) - items.SetProperty("tvshowthumb", art["thumb"]); + items.SetArt("tvshowthumb", art["thumb"]); if (art.find("fanart") != art.end()) - items.SetProperty("fanart_image", art["fanart"]); + items.SetArt("fanart", art["fanart"]); } CFileItem showItem(details.m_strShowPath, true); @@ -316,14 +316,14 @@ bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemL string seasonThumb = m_database.GetArtForItem(seasonID, "season", "thumb"); if (!seasonThumb.empty()) { - items.SetProperty("seasonthumb",seasonThumb); - items.SetThumbnailImage(seasonThumb); + items.SetArt("seasonthumb",seasonThumb); + items.SetArt("thumb", seasonThumb); } } else { items.SetContent("seasons"); - items.SetThumbnailImage(showItem.GetThumbnailImage()); + items.SetArt("thumb", showItem.GetArt("thumb")); } } else if (node == NODE_TYPE_TITLE_MOVIES || @@ -1119,7 +1119,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) if (!currentThumb.IsEmpty() && CFile::Exists(currentThumb)) { CFileItemPtr item(new CFileItem("thumb://Current", false)); - item->SetThumbnailImage(currentThumb); + item->SetArt("thumb", currentThumb); item->SetLabel(g_localizeStrings.Get(20016)); items.Add(item); } @@ -1135,7 +1135,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) else tag = *m_vecItems->Get(itemNumber)->GetVideoInfoTag(); if (button == CONTEXT_BUTTON_SET_SEASON_THUMB) - tag.m_strPictureURL.GetThumbURLs(thumbs, m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_iSeason); + tag.m_strPictureURL.GetThumbURLs(thumbs, "", m_vecItems->Get(itemNumber)->GetVideoInfoTag()->m_iSeason); else tag.m_strPictureURL.GetThumbURLs(thumbs); @@ -1144,7 +1144,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) CStdString strItemPath; strItemPath.Format("thumb://Remote%i",i); CFileItemPtr item(new CFileItem(strItemPath, false)); - item->SetThumbnailImage(thumbs[i]); + item->SetArt("thumb", thumbs[i]); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20015)); items.Add(item); @@ -1163,7 +1163,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) { CFileItemPtr pItem(new CFileItem(strThumb,false)); pItem->SetLabel(g_localizeStrings.Get(20017)); - pItem->SetThumbnailImage(strThumb); + pItem->SetArt("thumb", strThumb); items.Add(pItem); local = true; } @@ -1180,7 +1180,7 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) { CFileItemPtr pItem(new CFileItem(strThumb,false)); pItem->SetLabel(g_localizeStrings.Get(20017)); - pItem->SetThumbnailImage(strThumb); + pItem->SetArt("thumb", strThumb); items.Add(pItem); local = true; } @@ -1241,10 +1241,10 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) CVideoThumbLoader loader; loader.LoadItem(item.get()); - if (item->HasProperty("fanart_image")) + if (item->HasArt("fanart")) { CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); - itemCurrent->SetThumbnailImage(item->GetProperty("fanart_image").asString()); + itemCurrent->SetArt("thumb", item->GetArt("fanart")); itemCurrent->SetLabel(g_localizeStrings.Get(20440)); items.Add(itemCurrent); } diff --git a/xbmc/windows/GUIWindowFileManager.cpp b/xbmc/windows/GUIWindowFileManager.cpp index 3fe7fc516e..2727053762 100644 --- a/xbmc/windows/GUIWindowFileManager.cpp +++ b/xbmc/windows/GUIWindowFileManager.cpp @@ -511,7 +511,7 @@ bool CGUIWindowFileManager::Update(int iList, const CStdString &strDirectory) { CFileItemPtr pItem(new CFileItem("special://profile/", true)); pItem->SetLabel(g_localizeStrings.Get(20070)); - pItem->SetThumbnailImage("DefaultFolder.png"); + pItem->SetArt("thumb", "DefaultFolder.png"); pItem->SetLabelPreformated(true); m_vecItems[iList]->Add(pItem); } @@ -524,7 +524,7 @@ bool CGUIWindowFileManager::Update(int iList, const CStdString &strDirectory) URIUtils::GetExtension(pItem->GetPath(), strExtension); if (pItem->IsHD() && strExtension == ".tbn") { - pItem->SetThumbnailImage(pItem->GetPath()); + pItem->SetArt("thumb", pItem->GetPath()); } } m_vecItems[iList]->FillInDefaultIcons(); diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp index 1cdfb16512..0455b3a19b 100644 --- a/xbmc/windows/GUIWindowLoginScreen.cpp +++ b/xbmc/windows/GUIWindowLoginScreen.cpp @@ -198,9 +198,9 @@ void CGUIWindowLoginScreen::Update() else strLabel.Format(g_localizeStrings.Get(20112), profile->getDate()); item->SetLabel2(strLabel); - item->SetThumbnailImage(profile->getThumb()); + item->SetArt("thumb", profile->getThumb()); if (profile->getThumb().IsEmpty() || profile->getThumb().Equals("-")) - item->SetThumbnailImage("unknown-user.png"); + item->SetArt("thumb", "unknown-user.png"); item->SetLabelPreformated(true); m_vecItems->Add(item); } |