summaryrefslogtreecommitdiffstats
path: root/xbmc/pictures/PictureThumbLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/pictures/PictureThumbLoader.cpp')
-rw-r--r--xbmc/pictures/PictureThumbLoader.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp
new file mode 100644
index 0000000..0cdd56c
--- /dev/null
+++ b/xbmc/pictures/PictureThumbLoader.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "PictureThumbLoader.h"
+
+#include "FileItem.h"
+#include "GUIUserMessages.h"
+#include "Picture.h"
+#include "ServiceBroker.h"
+#include "TextureCache.h"
+#include "URL.h"
+#include "filesystem/Directory.h"
+#include "filesystem/MultiPathDirectory.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "utils/FileExtensionProvider.h"
+#include "utils/FileUtils.h"
+#include "utils/URIUtils.h"
+#include "video/VideoThumbLoader.h"
+
+using namespace XFILE;
+
+CPictureThumbLoader::CPictureThumbLoader() : CThumbLoader(), CJobQueue(true, 1, CJob::PRIORITY_LOW_PAUSABLE)
+{
+ m_regenerateThumbs = false;
+}
+
+CPictureThumbLoader::~CPictureThumbLoader()
+{
+ StopThread();
+}
+
+void CPictureThumbLoader::OnLoaderFinish()
+{
+ m_regenerateThumbs = false;
+ CThumbLoader::OnLoaderFinish();
+}
+
+bool CPictureThumbLoader::LoadItem(CFileItem* pItem)
+{
+ bool result = LoadItemCached(pItem);
+ result |= LoadItemLookup(pItem);
+
+ return result;
+}
+
+bool CPictureThumbLoader::LoadItemCached(CFileItem* pItem)
+{
+ if (pItem->m_bIsShareOrDrive
+ || pItem->IsParentFolder())
+ return false;
+
+ if (pItem->HasArt("thumb") && m_regenerateThumbs)
+ {
+ CServiceBroker::GetTextureCache()->ClearCachedImage(pItem->GetArt("thumb"));
+ if (m_textureDatabase->Open())
+ {
+ m_textureDatabase->ClearTextureForPath(pItem->GetPath(), "thumb");
+ m_textureDatabase->Close();
+ }
+ pItem->SetArt("thumb", "");
+ }
+
+ std::string thumb;
+ if (pItem->IsPicture() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList())
+ { // load the thumb from the image file
+ thumb = pItem->HasArt("thumb") ? pItem->GetArt("thumb") : CTextureUtils::GetWrappedThumbURL(pItem->GetPath());
+ }
+ else if (pItem->IsVideo() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList())
+ { // video
+ CVideoThumbLoader loader;
+ if (!loader.FillThumb(*pItem))
+ {
+ std::string thumbURL = CVideoThumbLoader::GetEmbeddedThumbURL(*pItem);
+ if (CServiceBroker::GetTextureCache()->HasCachedImage(thumbURL))
+ {
+ thumb = thumbURL;
+ }
+ else if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MYVIDEOS_EXTRACTTHUMB) && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_MYVIDEOS_EXTRACTFLAGS))
+ {
+ CFileItem item(*pItem);
+ CThumbExtractor* extract = new CThumbExtractor(item, pItem->GetPath(), true, thumbURL);
+ AddJob(extract);
+ thumb.clear();
+ }
+ }
+ }
+ else if (!pItem->HasArt("thumb"))
+ { // folder, zip, cbz, rar, cbr, playlist may have a previously cached image
+ thumb = GetCachedImage(*pItem, "thumb");
+ }
+ if (!thumb.empty())
+ {
+ CServiceBroker::GetTextureCache()->BackgroundCacheImage(thumb);
+ pItem->SetArt("thumb", thumb);
+ }
+ pItem->FillInDefaultIcon();
+ return true;
+}
+
+bool CPictureThumbLoader::LoadItemLookup(CFileItem* pItem)
+{
+ return false;
+}
+
+void CPictureThumbLoader::OnJobComplete(unsigned int jobID, bool success, CJob* job)
+{
+ if (success)
+ {
+ CThumbExtractor* loader = static_cast<CThumbExtractor*>(job);
+ loader->m_item.SetPath(loader->m_listpath);
+ CFileItemPtr pItem(new CFileItem(loader->m_item));
+ CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, pItem);
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
+ }
+ CJobQueue::OnJobComplete(jobID, success, job);
+}
+
+void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem)
+{
+ if (pItem->HasArt("thumb"))
+ return;
+
+ CTextureDatabase db;
+ db.Open();
+ if (pItem->IsCBR() || pItem->IsCBZ())
+ {
+ std::string strTBN(URIUtils::ReplaceExtension(pItem->GetPath(),".tbn"));
+ if (CFileUtils::Exists(strTBN))
+ {
+ db.SetTextureForPath(pItem->GetPath(), "thumb", strTBN);
+ CServiceBroker::GetTextureCache()->BackgroundCacheImage(strTBN);
+ pItem->SetArt("thumb", strTBN);
+ return;
+ }
+ }
+ if ((pItem->m_bIsFolder || pItem->IsCBR() || pItem->IsCBZ()) && !pItem->m_bIsShareOrDrive
+ && !pItem->IsParentFolder() && !pItem->IsPath("add"))
+ {
+ // first check for a folder.jpg
+ std::string thumb = "folder.jpg";
+ CURL pathToUrl = pItem->GetURL();
+ if (pItem->IsCBR())
+ {
+ pathToUrl = URIUtils::CreateArchivePath("rar",pItem->GetURL(),"");
+ thumb = "cover.jpg";
+ }
+ if (pItem->IsCBZ())
+ {
+ pathToUrl = URIUtils::CreateArchivePath("zip",pItem->GetURL(),"");
+ thumb = "cover.jpg";
+ }
+ if (pItem->IsMultiPath())
+ pathToUrl = CURL(CMultiPathDirectory::GetFirstPath(pItem->GetPath()));
+ thumb = URIUtils::AddFileToFolder(pathToUrl.Get(), thumb);
+ if (CFileUtils::Exists(thumb))
+ {
+ db.SetTextureForPath(pItem->GetPath(), "thumb", thumb);
+ CServiceBroker::GetTextureCache()->BackgroundCacheImage(thumb);
+ pItem->SetArt("thumb", thumb);
+ return;
+ }
+ if (!pItem->IsPlugin())
+ {
+ // we load the directory, grab 4 random thumb files (if available) and then generate
+ // the thumb.
+
+ CFileItemList items;
+
+ CDirectory::GetDirectory(pathToUrl, items, CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), DIR_FLAG_NO_FILE_DIRS);
+
+ // create the folder thumb by choosing 4 random thumbs within the folder and putting
+ // them into one thumb.
+ // count the number of images
+ for (int i=0; i < items.Size();)
+ {
+ if (!items[i]->IsPicture() || items[i]->IsZIP() || items[i]->IsRAR() || items[i]->IsPlayList())
+ {
+ items.Remove(i);
+ }
+ else
+ i++;
+ }
+
+ if (items.IsEmpty())
+ {
+ if (pItem->IsCBZ() || pItem->IsCBR())
+ {
+ CDirectory::GetDirectory(pathToUrl, items, CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), DIR_FLAG_NO_FILE_DIRS);
+ for (int i=0;i<items.Size();++i)
+ {
+ CFileItemPtr item = items[i];
+ if (item->m_bIsFolder)
+ {
+ ProcessFoldersAndArchives(item.get());
+ pItem->SetArt("thumb", items[i]->GetArt("thumb"));
+ pItem->SetArt("icon", items[i]->GetArt("icon"));
+ return;
+ }
+ }
+ }
+ return; // no images in this folder
+ }
+
+ // randomize them
+ items.Randomize();
+
+ if (items.Size() < 4 || pItem->IsCBR() || pItem->IsCBZ())
+ { // less than 4 items, so just grab the first thumb
+ items.Sort(SortByLabel, SortOrderAscending);
+ std::string thumb = CTextureUtils::GetWrappedThumbURL(items[0]->GetPath());
+ db.SetTextureForPath(pItem->GetPath(), "thumb", thumb);
+ CServiceBroker::GetTextureCache()->BackgroundCacheImage(thumb);
+ pItem->SetArt("thumb", thumb);
+ }
+ else
+ {
+ // ok, now we've got the files to get the thumbs from, lets create it...
+ // we basically load the 4 images and combine them
+ std::vector<std::string> files;
+ files.reserve(4);
+ for (int thumb = 0; thumb < 4; thumb++)
+ files.push_back(items[thumb]->GetPath());
+ std::string thumb = CTextureUtils::GetWrappedImageURL(pItem->GetPath(), "picturefolder");
+ std::string relativeCacheFile = CTextureCache::GetCacheFile(thumb) + ".png";
+ if (CPicture::CreateTiledThumb(files, CTextureCache::GetCachedPath(relativeCacheFile)))
+ {
+ CTextureDetails details;
+ details.file = relativeCacheFile;
+ details.width = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_imageRes;
+ details.height = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_imageRes;
+ CServiceBroker::GetTextureCache()->AddCachedTexture(thumb, details);
+ db.SetTextureForPath(pItem->GetPath(), "thumb", thumb);
+ pItem->SetArt("thumb", CTextureCache::GetCachedPath(relativeCacheFile));
+ }
+ }
+ }
+ // refill in the icon to get it to update
+ pItem->FillInDefaultIcon();
+ }
+}