aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Rector <rmrector@gmail.com>2020-08-21 22:39:49 -0600
committerRyan Rector <rmrector@gmail.com>2020-10-03 15:45:58 -0600
commit08825f55bbccf272054761c3126d7b407695543b (patch)
tree59e8161a6de76c275b9a7342e454c906ccec80d8
parentddcbadf2c0f631cddd58ea36d926beebc27dc363 (diff)
add GUI configuration for artwork
-rw-r--r--addons/resource.language.en_gb/resources/strings.po43
-rwxr-xr-xsystem/settings/settings.xml107
-rw-r--r--xbmc/FileItem.cpp24
-rw-r--r--xbmc/FileItem.h19
-rw-r--r--xbmc/settings/AdvancedSettings.cpp40
-rw-r--r--xbmc/settings/Settings.cpp12
-rw-r--r--xbmc/settings/Settings.h11
-rw-r--r--xbmc/video/VideoInfoScanner.cpp170
-rw-r--r--xbmc/video/VideoInfoScanner.h21
-rw-r--r--xbmc/video/VideoThumbLoader.cpp131
-rw-r--r--xbmc/video/VideoThumbLoader.h4
11 files changed, 439 insertions, 143 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index df337cf8f6..f005cf1302 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -22247,4 +22247,47 @@ msgstr ""
#: system/settings/settings.xml
msgctxt "#39142"
msgid "Custom"
+
+#: system/settings/settings.xml
+msgctxt "#39143"
+msgid "Movie art types whitelist"
+msgstr ""
+
+#. Description of setting with label #39150 "Movie art types whitelist"
+#: system/settings/settings.xml
+msgctxt "#39144"
+msgid "Limit the movie and movie set artwork fetched locally or applied from scraper remote art results to just those art types in the whitelist"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#39145"
+msgid "TV show art types whitelist"
+msgstr ""
+
+#. Description of setting with label #39152 "TV show art types whitelist"
+#: system/settings/settings.xml
+msgctxt "#39146"
+msgid "Limit the TV show and season artwork fetched locally or applied from scraper remote art results to just those art types in the whitelist"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#39147"
+msgid "Episode art types whitelist"
+msgstr ""
+
+#. Description of setting with label #39154 "Episode art types whitelist"
+#: system/settings/settings.xml
+msgctxt "#39148"
+msgid "Limit the episode artwork fetched locally or applied from scraper remote art results to just those art types in the whitelist"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#39149"
+msgid "Music video art types whitelist"
+msgstr ""
+
+#. Description of setting with label #39156 "Music video art types whitelist"
+#: system/settings/settings.xml
+msgctxt "#39150"
+msgid "Limit the music video artwork fetched locally or applied from scraper remote art results to just those art types in the whitelist"
msgstr ""
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index e6c10e26e0..893a64e2b4 100755
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -1000,6 +1000,113 @@
</control>
</setting>
</group>
+ <group id="4" label="39123">
+ <!-- Hidden setting indicating video art settings have been migrated from old advancedsettings.xml format-->
+ <setting id="videolibrary.artsettingsupdated" type="boolean" label="0" help="">
+ <level>4</level>
+ <default>false</default>
+ <control type="toggle" />
+ </setting>
+ <setting id="videolibrary.artworklevel" type="integer" label="39137" help="39138">
+ <level>1</level>
+ <default>0</default>
+ <constraints>
+ <options>
+ <option label="39140">0</option> <!-- VIDEOLIBRARY_ARTWORK_LEVEL_ALL -->
+ <option label="39141">1</option> <!-- VIDEOLIBRARY_ARTWORK_LEVEL_BASIC -->
+ <option label="39142">2</option> <!-- VIDEOLIBRARY_ARTWORK_LEVEL_CUSTOM -->
+ <option label="231">3</option> <!-- VIDEOLIBRARY_ARTWORK_LEVEL_NONE -->
+ </options>
+ </constraints>
+ <control type="list" format="string" />
+ </setting>
+ <setting id="videolibrary.movieartwhitelist" type="list[string]" parent="videolibrary.artworklevel" label="39143" help="39144">
+ <level>2</level>
+ <default></default>
+ <constraints>
+ <options>
+ <option>clearart</option>
+ <option>discart</option>
+ <option>keyart</option>
+ <option>banner</option>
+ <option>landscape</option>
+ <option>clearlogo</option>
+ </options>
+ <delimiter>, </delimiter>
+ <allownewoption>true</allownewoption>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videolibrary.artworklevel" operator="is">2</dependency>
+ </dependencies>
+ <control type="list" format="string">
+ <multiselect>true</multiselect>
+ <addbuttonlabel>13516</addbuttonlabel>
+ </control>
+ </setting>
+ <setting id="videolibrary.tvshowartwhitelist" type="list[string]" parent="videolibrary.artworklevel" label="39145" help="39146">
+ <level>2</level>
+ <default></default>
+ <constraints>
+ <options>
+ <option>clearart</option>
+ <option>discart</option>
+ <option>keyart</option>
+ <option>banner</option>
+ <option>landscape</option>
+ <option>clearlogo</option>
+ </options>
+ <delimiter>, </delimiter>
+ <allownewoption>true</allownewoption>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videolibrary.artworklevel" operator="is">2</dependency>
+ </dependencies>
+ <control type="list" format="string">
+ <multiselect>true</multiselect>
+ <addbuttonlabel>13516</addbuttonlabel>
+ </control>
+ </setting>
+ <setting id="videolibrary.episodeartwhitelist" type="list[string]" parent="videolibrary.artworklevel" label="39147" help="39148">
+ <level>2</level>
+ <default></default>
+ <constraints>
+ <options>
+ <option>fanart</option>
+ </options>
+ <delimiter>, </delimiter>
+ <allownewoption>true</allownewoption>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videolibrary.artworklevel" operator="is">2</dependency>
+ </dependencies>
+ <control type="list" format="string">
+ <multiselect>true</multiselect>
+ <addbuttonlabel>13516</addbuttonlabel>
+ </control>
+ </setting>
+ <setting id="videolibrary.musicvideoartwhitelist" type="list[string]" parent="videolibrary.artworklevel" label="39149" help="39150">
+ <level>2</level>
+ <default></default>
+ <constraints>
+ <options>
+ <option>clearart</option>
+ <option>discart</option>
+ <option>banner</option>
+ <option>landscape</option>
+ <option>clearlogo</option>
+ </options>
+ <delimiter>, </delimiter>
+ <allownewoption>true</allownewoption>
+ </constraints>
+ <dependencies>
+ <dependency type="visible" setting="videolibrary.artworklevel" operator="is">2</dependency>
+ </dependencies>
+ <control type="list" format="string">
+ <multiselect>true</multiselect>
+ <addbuttonlabel>13516</addbuttonlabel>
+ </control>
+ </setting>
+ </group>
</category>
<category id="music" label="14216" help="38108">
<group id="1" label="39121">
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp
index c2f054992d..a268b256f6 100644
--- a/xbmc/FileItem.cpp
+++ b/xbmc/FileItem.cpp
@@ -3220,19 +3220,17 @@ std::string CFileItem::FindLocalArt(const std::string &artFile, bool useFolder)
return "";
}
-std::string CFileItem::GetLocalArt(const std::string &artFile, bool useFolder) const
+std::string CFileItem::GetLocalArtBaseFilename() const
{
- // no retrieving of empty art files from folders
- if (useFolder && artFile.empty())
- return "";
+ bool useFolder = false;
+ return GetLocalArtBaseFilename(useFolder);
+}
+std::string CFileItem::GetLocalArtBaseFilename(bool& useFolder) const
+{
std::string strFile = m_strPath;
if (IsStack())
{
-/* CFileItem item(CStackDirectory::GetFirstStackedFile(strFile),false);
- std::string localArt = item.GetLocalArt(artFile);
- return localArt;
- */
std::string strPath;
URIUtils::GetParentPath(m_strPath,strPath);
strFile = URIUtils::AddFileToFolder(strPath, URIUtils::GetFileName(CStackDirectory::GetStackedTitlePath(strFile)));
@@ -3257,6 +3255,16 @@ std::string CFileItem::GetLocalArt(const std::string &artFile, bool useFolder) c
else if (useFolder && !(m_bIsFolder && !IsFileFolder()))
strFile = URIUtils::GetDirectory(strFile);
+ return strFile;
+}
+
+std::string CFileItem::GetLocalArt(const std::string& artFile, bool useFolder) const
+{
+ // no retrieving of empty art files from folders
+ if (useFolder && artFile.empty())
+ return "";
+
+ std::string strFile = GetLocalArtBaseFilename(useFolder);
if (strFile.empty()) // empty filepath -> nothing to find
return "";
diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h
index 347009d7d1..305db92632 100644
--- a/xbmc/FileItem.h
+++ b/xbmc/FileItem.h
@@ -385,6 +385,23 @@ public:
*/
std::string GetLocalFanart() const;
+ /*!
+ \brief Assemble the base filename of local artwork for an item,
+ accounting for archives, stacks and multi-paths, and BDMV/VIDEO_TS folders.
+ `useFolder` is set to false
+ \return the path to the base filename for artwork lookup.
+ \sa GetLocalArt
+ */
+ std::string GetLocalArtBaseFilename() const;
+ /*!
+ \brief Assemble the base filename of local artwork for an item,
+ accounting for archives, stacks and multi-paths, and BDMV/VIDEO_TS folders.
+ \param useFolder whether to look in the folder for the art file. Defaults to false.
+ \return the path to the base filename for artwork lookup.
+ \sa GetLocalArt
+ */
+ std::string GetLocalArtBaseFilename(bool& useFolder) 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.
@@ -392,7 +409,7 @@ public:
\return the path to the local artwork.
\sa FindLocalArt
*/
- std::string GetLocalArt(const std::string &artFile, bool useFolder = false) const;
+ std::string 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.
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
index 910b5e1ffe..e4a2d57ea9 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -1440,4 +1440,44 @@ void CAdvancedSettings::MigrateOldArtSettings()
// Flag migration of settings so not done again
settings->SetBool(CSettings::SETTING_MUSICLIBRARY_ARTSETTINGS_UPDATED, true);
}
+
+ if (!settings->GetBool(CSettings::SETTING_VIDEOLIBRARY_ARTSETTINGS_UPDATED))
+ {
+ CLog::Log(LOGINFO, "Migrating old video library artwork settings to new GUI settings");
+ // Convert numeric art type variants into simple art type family entry
+ // e.g. {"banner", "fanart1", "fanart2", "fanart3"... } into { "banner", "fanart"}
+ if (!m_videoEpisodeExtraArt.empty())
+ {
+ std::vector<CVariant> whitelist;
+ ConvertToWhitelist(m_videoEpisodeExtraArt, whitelist);
+ settings->SetList(CSettings::SETTING_VIDEOLIBRARY_EPISODEART_WHITELIST, whitelist);
+ }
+ if (!m_videoTvShowExtraArt.empty())
+ {
+ std::vector<CVariant> whitelist;
+ ConvertToWhitelist(m_videoTvShowExtraArt, whitelist);
+ settings->SetList(CSettings::SETTING_VIDEOLIBRARY_TVSHOWART_WHITELIST, whitelist);
+ }
+ if (!m_videoMovieExtraArt.empty())
+ {
+ std::vector<CVariant> whitelist;
+ ConvertToWhitelist(m_videoMovieExtraArt, whitelist);
+ settings->SetList(CSettings::SETTING_VIDEOLIBRARY_MOVIEART_WHITELIST, whitelist);
+ }
+ if (!m_videoMusicVideoExtraArt.empty())
+ {
+ std::vector<CVariant> whitelist;
+ ConvertToWhitelist(m_videoMusicVideoExtraArt, whitelist);
+ settings->SetList(CSettings::SETTING_VIDEOLIBRARY_MUSICVIDEOART_WHITELIST, whitelist);
+ }
+
+ // Whitelists configured, set artwork level to custom
+ if (!m_videoEpisodeExtraArt.empty() || !m_videoTvShowExtraArt.empty()
+ || !m_videoMovieExtraArt.empty() || !m_videoMusicVideoExtraArt.empty())
+ settings->SetInt(CSettings::SETTING_VIDEOLIBRARY_ARTWORK_LEVEL,
+ CSettings::MUSICLIBRARY_ARTWORK_LEVEL_CUSTOM);
+
+ // Flag migration of settings so not done again
+ settings->SetBool(CSettings::SETTING_VIDEOLIBRARY_ARTSETTINGS_UPDATED, true);
+ }
}
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index f187e13653..b71c4ba8b9 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -115,6 +115,18 @@ const std::string CSettings::SETTING_VIDEOLIBRARY_EXPORT = "videolibrary.export"
const std::string CSettings::SETTING_VIDEOLIBRARY_IMPORT = "videolibrary.import";
const std::string CSettings::SETTING_VIDEOLIBRARY_SHOWEMPTYTVSHOWS = "videolibrary.showemptytvshows";
const std::string CSettings::SETTING_VIDEOLIBRARY_MOVIESETSFOLDER = "videolibrary.moviesetsfolder";
+const std::string CSettings::SETTING_VIDEOLIBRARY_ARTWORK_LEVEL =
+ "videolibrary.artworklevel";
+const std::string CSettings::SETTING_VIDEOLIBRARY_MOVIEART_WHITELIST =
+ "videolibrary.movieartwhitelist";
+const std::string CSettings::SETTING_VIDEOLIBRARY_TVSHOWART_WHITELIST =
+ "videolibrary.tvshowartwhitelist";
+const std::string CSettings::SETTING_VIDEOLIBRARY_EPISODEART_WHITELIST =
+ "videolibrary.episodeartwhitelist";
+const std::string CSettings::SETTING_VIDEOLIBRARY_MUSICVIDEOART_WHITELIST =
+ "videolibrary.musicvideoartwhitelist";
+const std::string CSettings::SETTING_VIDEOLIBRARY_ARTSETTINGS_UPDATED =
+ "videolibrary.artsettingsupdated";
const std::string CSettings::SETTING_LOCALE_AUDIOLANGUAGE = "locale.audiolanguage";
const std::string CSettings::SETTING_VIDEOPLAYER_PREFERDEFAULTFLAG = "videoplayer.preferdefaultflag";
const std::string CSettings::SETTING_VIDEOPLAYER_AUTOPLAYNEXTITEM = "videoplayer.autoplaynextitem";
diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h
index c01ba3e7a1..3d6d6e1aba 100644
--- a/xbmc/settings/Settings.h
+++ b/xbmc/settings/Settings.h
@@ -83,6 +83,12 @@ public:
static const std::string SETTING_VIDEOLIBRARY_IMPORT;
static const std::string SETTING_VIDEOLIBRARY_SHOWEMPTYTVSHOWS;
static const std::string SETTING_VIDEOLIBRARY_MOVIESETSFOLDER;
+ static const std::string SETTING_VIDEOLIBRARY_ARTWORK_LEVEL;
+ static const std::string SETTING_VIDEOLIBRARY_MOVIEART_WHITELIST;
+ static const std::string SETTING_VIDEOLIBRARY_TVSHOWART_WHITELIST;
+ static const std::string SETTING_VIDEOLIBRARY_EPISODEART_WHITELIST;
+ static const std::string SETTING_VIDEOLIBRARY_MUSICVIDEOART_WHITELIST;
+ static const std::string SETTING_VIDEOLIBRARY_ARTSETTINGS_UPDATED;
static const std::string SETTING_LOCALE_AUDIOLANGUAGE;
static const std::string SETTING_VIDEOPLAYER_PREFERDEFAULTFLAG;
static const std::string SETTING_VIDEOPLAYER_AUTOPLAYNEXTITEM;
@@ -395,6 +401,11 @@ public:
static const int VIDEOLIBRARY_PLOTS_SHOW_UNWATCHED_MOVIES = 0;
static const int VIDEOLIBRARY_PLOTS_SHOW_UNWATCHED_TVSHOWEPISODES = 1;
static const int VIDEOLIBRARY_THUMB_SHOW_UNWATCHED_EPISODE = 2;
+ // values for SETTING_VIDEOLIBRARY_ARTWORK_LEVEL
+ static const int VIDEOLIBRARY_ARTWORK_LEVEL_ALL = 0;
+ static const int VIDEOLIBRARY_ARTWORK_LEVEL_BASIC = 1;
+ static const int VIDEOLIBRARY_ARTWORK_LEVEL_CUSTOM = 2;
+ static const int VIDEOLIBRARY_ARTWORK_LEVEL_NONE = 3;
// values for SETTING_MUSICLIBRARY_ARTWORKLEVEL
static const int MUSICLIBRARY_ARTWORK_LEVEL_ALL = 0;
diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp
index 6d1f7dbed5..8ee1f830ce 100644
--- a/xbmc/video/VideoInfoScanner.cpp
+++ b/xbmc/video/VideoInfoScanner.cpp
@@ -1445,6 +1445,7 @@ namespace VIDEO
if (path.empty())
return "";
path = URIUtils::AddFileToFolder(path, CUtil::MakeLegalFileName(setTitle, LEGAL_WIN32_COMPAT));
+ URIUtils::AddSlashAtEnd(path);
CLog::Log(LOGDEBUG,
"VideoInfoScanner: Looking for local artwork for movie set '{}' in folder '{}'",
setTitle,
@@ -1452,10 +1453,11 @@ namespace VIDEO
return CDirectory::Exists(path) ? path : "";
}
- void CVideoInfoScanner::GetLocalMovieSetArtwork(CGUIListItem::ArtMap& art,
- const std::vector<std::string>& artTypes, const std::string& setTitle)
+ void CVideoInfoScanner::AddLocalItemArtwork(CGUIListItem::ArtMap& itemArt,
+ const std::vector<std::string>& wantedArtTypes, const std::string& itemPath,
+ bool addAll, bool exactName)
{
- std::string path = GetMovieSetInfoFolder(setTitle);
+ std::string path = URIUtils::GetDirectory(itemPath);
if (path.empty())
return;
@@ -1464,21 +1466,47 @@ namespace VIDEO
CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(),
DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO);
+ std::string baseFilename = URIUtils::GetFileName(itemPath);
+ if (!baseFilename.empty())
+ {
+ URIUtils::RemoveExtension(baseFilename);
+ baseFilename.append("-");
+ }
+
for (const auto& artFile : availableArtFiles)
{
std::string candidate = URIUtils::GetFileName(artFile->GetPath());
+
+ bool matchesFilename =
+ !baseFilename.empty() && StringUtils::StartsWith(candidate, baseFilename);
+ if (!baseFilename.empty() && !matchesFilename)
+ continue;
+
+ if (matchesFilename)
+ candidate.erase(0, baseFilename.length());
URIUtils::RemoveExtension(candidate);
- for (const auto& artType : artTypes)
+ StringUtils::ToLower(candidate);
+
+ // move 'folder' to thumb / poster / banner based on aspect ratio
+ // if such artwork doesn't already exist
+ if (!matchesFilename && StringUtils::EqualsNoCase(candidate, "folder") &&
+ !CVideoThumbLoader::IsArtTypeInWhitelist("folder", wantedArtTypes, exactName))
{
- if (!StringUtils::StartsWith(artType, "set."))
- continue;
- std::string realType = artType.substr(4);
- if (StringUtils::EqualsNoCase(candidate, realType))
+ // cache the image to determine sizing
+ CTextureDetails details;
+ if (CTextureCache::GetInstance().CacheImage(artFile->GetPath(), details))
{
- art[artType] = artFile->GetPath();
- break;
+ candidate = GetArtTypeFromSize(details.width, details.height);
+ if (itemArt.find(candidate) != itemArt.end())
+ continue;
}
}
+
+ if ((addAll && CVideoThumbLoader::IsValidArtType(candidate)) ||
+ CVideoThumbLoader::IsArtTypeInWhitelist(candidate, wantedArtTypes, exactName))
+ {
+ itemArt[candidate] = artFile->GetPath();
+ }
}
}
@@ -1491,41 +1519,45 @@ namespace VIDEO
CGUIListItem::ArtMap art = pItem->GetArt();
// get and cache thumb images
- std::vector<std::string> artTypes = CVideoThumbLoader::GetArtTypes(ContentToMediaType(content, pItem->m_bIsFolder));
- bool lookForThumb = find(artTypes.begin(), artTypes.end(), "thumb") == artTypes.end() &&
- art.find("thumb") == art.end();
+ std::string mediaType = ContentToMediaType(content, pItem->m_bIsFolder);
+ std::vector<std::string> artTypes = CVideoThumbLoader::GetArtTypes(mediaType);
bool moviePartOfSet = content == CONTENT_MOVIES && !movieDetails.m_set.title.empty();
+ std::vector<std::string> movieSetArtTypes;
if (moviePartOfSet)
{
- for (std::string artType : CVideoThumbLoader::GetArtTypes(MediaTypeVideoCollection))
+ movieSetArtTypes = CVideoThumbLoader::GetArtTypes(MediaTypeVideoCollection);
+ for (std::string artType : movieSetArtTypes)
artTypes.push_back("set." + artType);
}
+ int artLevel = CServiceBroker::GetSettingsComponent()->GetSettings()->
+ GetInt(CSettings::SETTING_VIDEOLIBRARY_ARTWORK_LEVEL);
+ bool addAll = artLevel == CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_ALL;
+ bool exactName = artLevel == CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_BASIC;
// find local art
if (useLocal)
{
- for (std::vector<std::string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i)
+ if (!pItem->SkipLocalArt())
{
- if (art.find(*i) == art.end())
+ if (bApplyToDir && (content == CONTENT_MOVIES || content == CONTENT_MUSICVIDEOS))
{
- std::string image = CVideoThumbLoader::GetLocalArt(*pItem, *i, bApplyToDir);
- if (!image.empty())
- art.insert(std::make_pair(*i, image));
+ std::string filename = pItem->GetLocalArtBaseFilename();
+ std::string directory = URIUtils::GetDirectory(filename);
+ if (filename != directory)
+ AddLocalItemArtwork(art, artTypes, directory, addAll, exactName);
}
+ AddLocalItemArtwork(art, artTypes, pItem->GetLocalArtBaseFilename(), addAll, exactName);
}
+
if (moviePartOfSet)
- GetLocalMovieSetArtwork(art, artTypes, movieDetails.m_set.title);
- // find and classify the local thumb (backcompat) if available
- if (lookForThumb)
{
- std::string image = CVideoThumbLoader::GetLocalArt(*pItem, "thumb", bApplyToDir);
- if (!image.empty())
- { // cache the image and determine sizing
- CTextureDetails details;
- if (CTextureCache::GetInstance().CacheImage(image, details))
+ std::string movieSetInfoPath = GetMovieSetInfoFolder(movieDetails.m_set.title);
+ if (!movieSetInfoPath.empty())
+ {
+ CGUIListItem::ArtMap movieSetArt;
+ AddLocalItemArtwork(movieSetArt, movieSetArtTypes, movieSetInfoPath, addAll, exactName);
+ for (const auto& artItem : movieSetArt)
{
- std::string type = GetArtTypeFromSize(details.width, details.height);
- if (art.find(type) == art.end())
- art.insert(std::make_pair(type, image));
+ art["set." + artItem.first] = artItem.second;
}
}
}
@@ -1536,7 +1568,8 @@ namespace VIDEO
{
for (auto& it : pItem->GetVideoInfoTag()->m_coverArt)
{
- if (std::find(artTypes.begin(), artTypes.end(), it.m_type) != artTypes.end() && art.find(it.m_type) == art.end())
+ if ((addAll || CVideoThumbLoader::IsArtTypeInWhitelist(it.m_type, artTypes, exactName)) &&
+ art.find(it.m_type) == art.end())
{
std::string thumb = CTextureUtils::GetWrappedImageURL(pItem->GetPath(),
"video_" + it.m_type);
@@ -1546,7 +1579,8 @@ namespace VIDEO
}
// add online fanart (treated separately due to it being stored in m_fanart)
- if (find(artTypes.begin(), artTypes.end(), "fanart") != artTypes.end() && art.find("fanart") == art.end())
+ if ((addAll || CVideoThumbLoader::IsArtTypeInWhitelist("fanart", artTypes, exactName)) &&
+ art.find("fanart") == art.end())
{
std::string fanart = pItem->GetVideoInfoTag()->m_fanart.GetImageURL();
if (!fanart.empty())
@@ -1561,16 +1595,22 @@ namespace VIDEO
std::string aspect = url.m_aspect;
if (aspect.empty())
// Backward compatibility with Kodi 11 Eden NFO files
- aspect = ContentToMediaType(content, pItem->m_bIsFolder) == MediaTypeEpisode ? "thumb" : "poster";
- if (find(artTypes.begin(), artTypes.end(), aspect) == artTypes.end() || art.find(aspect) != art.end())
- continue;
- std::string image = GetImage(url, pItem->GetPath());
- if (!image.empty())
- art.insert(std::make_pair(aspect, image));
+ aspect = mediaType == MediaTypeEpisode ? "thumb" : "poster";
+
+ if ((addAll || CVideoThumbLoader::IsArtTypeInWhitelist(aspect, artTypes, exactName)) &&
+ art.find(aspect) == art.end())
+ {
+ std::string image = GetImage(url, pItem->GetPath());
+ if (!image.empty())
+ art.insert(std::make_pair(aspect, image));
+ }
}
- for (CGUIListItem::ArtMap::const_iterator i = art.begin(); i != art.end(); ++i)
- CTextureCache::GetInstance().BackgroundCacheImage(i->second);
+ for (const auto& artType : artTypes)
+ {
+ if (art.find(artType) != art.end())
+ CTextureCache::GetInstance().BackgroundCacheImage(art[artType]);
+ }
pItem->SetArt(art);
@@ -1965,16 +2005,21 @@ namespace VIDEO
void CVideoInfoScanner::GetSeasonThumbs(const CVideoInfoTag &show,
std::map<int, std::map<std::string, std::string>> &seasonArt, const std::vector<std::string> &artTypes, bool useLocal)
{
+ int artLevel = CServiceBroker::GetSettingsComponent()->GetSettings()->
+ GetInt(CSettings::SETTING_VIDEOLIBRARY_ARTWORK_LEVEL);
+ bool addAll = artLevel == CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_ALL;
+ bool exactName = artLevel == CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_BASIC;
if (useLocal)
{
- bool lookForThumb = find(artTypes.begin(), artTypes.end(), "thumb") == artTypes.end();
-
// find the maximum number of seasons we have local thumbs for
int maxSeasons = 0;
CFileItemList items;
- CDirectory::GetDirectory(show.m_strPath, items, ".png|.jpg|.tbn", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_NO_FILE_INFO);
+ std::string extensions = CServiceBroker::GetFileExtensionProvider().GetPictureExtensions();
+ CDirectory::GetDirectory(show.m_strPath, items, extensions,
+ DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO);
+ extensions.erase(std::remove(extensions.begin(), extensions.end(), '.'), extensions.end());
CRegExp reg;
- if (items.Size() && reg.RegComp("season([0-9]+)(-[a-z]+)?\\.(tbn|jpg|png)"))
+ if (items.Size() && reg.RegComp("season([0-9]+)(-[a-z0-9]+)?\\.(" + extensions + ")"))
{
for (const auto& item : items)
{
@@ -2002,29 +2047,10 @@ namespace VIDEO
basePath = "season-specials";
else
basePath = StringUtils::Format("season%02i", season);
- CFileItem artItem(URIUtils::AddFileToFolder(show.m_strPath, basePath), false);
- for (std::vector<std::string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i)
- {
- std::string image = CVideoThumbLoader::GetLocalArt(artItem, *i, false);
- if (!image.empty())
- art.insert(std::make_pair(*i, image));
- }
- // find and classify the local thumb (backcompat) if available
- if (lookForThumb)
- {
- std::string image = CVideoThumbLoader::GetLocalArt(artItem, "thumb", false);
- if (!image.empty())
- { // cache the image and determine sizing
- CTextureDetails details;
- if (CTextureCache::GetInstance().CacheImage(image, details))
- {
- std::string type = GetArtTypeFromSize(details.width, details.height);
- if (art.find(type) == art.end())
- art.insert(std::make_pair(type, image));
- }
- }
- }
+ AddLocalItemArtwork(art, artTypes,
+ URIUtils::AddFileToFolder(show.m_strPath, basePath),
+ addAll, exactName);
seasonArt[season] = art;
}
@@ -2038,11 +2064,13 @@ namespace VIDEO
if (aspect.empty())
aspect = "thumb";
std::map<std::string, std::string>& art = seasonArt[url.m_season];
- if (find(artTypes.begin(), artTypes.end(), aspect) == artTypes.end() || art.find(aspect) != art.end())
- continue;
- std::string image = CScraperUrl::GetThumbUrl(url);
- if (!image.empty())
- art.insert(std::make_pair(aspect, image));
+ if ((addAll || CVideoThumbLoader::IsArtTypeInWhitelist(aspect, artTypes, exactName)) &&
+ art.find(aspect) == art.end())
+ {
+ std::string image = CScraperUrl::GetThumbUrl(url);
+ if (!image.empty())
+ art.insert(std::make_pair(aspect, image));
+ }
}
}
diff --git a/xbmc/video/VideoInfoScanner.h b/xbmc/video/VideoInfoScanner.h
index 7c221aaf3d..f50c228d1b 100644
--- a/xbmc/video/VideoInfoScanner.h
+++ b/xbmc/video/VideoInfoScanner.h
@@ -91,14 +91,6 @@ namespace VIDEO
*/
void GetArtwork(CFileItem *pItem, const CONTENT_TYPE &content, bool bApplyToDir=false, bool useLocal=true, const std::string &actorArtPath = "");
- /*! \brief Retrieve the art type for an image from the given size.
- \param width the width of the image.
- \param height the height of the image.
- \return "poster" if the aspect ratio is at most 4:5, "banner" if the aspect ratio
- is at least 1:4, "thumb" otherwise.
- */
- static std::string GetArtTypeFromSize(unsigned int width, unsigned int height);
-
/*! \brief Get season thumbs for a tvshow.
All seasons (regardless of whether the user has episodes) are added to the art map.
\param show tvshow info tag
@@ -244,8 +236,17 @@ namespace VIDEO
std::set<int> m_pathsToClean;
private:
- void GetLocalMovieSetArtwork(CGUIListItem::ArtMap& art,
- const std::vector<std::string>& artTypes, const std::string& setTitle);
+ static void AddLocalItemArtwork(CGUIListItem::ArtMap& itemArt,
+ const std::vector<std::string>& wantedArtTypes, const std::string& itemPath,
+ bool addAll, bool exactName);
+
+ /*! \brief Retrieve the art type for an image from the given size.
+ \param width the width of the image.
+ \param height the height of the image.
+ \return "poster" if the aspect ratio is at most 4:5, "banner" if the aspect ratio
+ is at least 1:4, "thumb" otherwise.
+ */
+ static std::string GetArtTypeFromSize(unsigned int width, unsigned int height);
};
}
diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp
index 4610233ecc..b2fee57676 100644
--- a/xbmc/video/VideoThumbLoader.cpp
+++ b/xbmc/video/VideoThumbLoader.cpp
@@ -223,68 +223,93 @@ static void SetupRarOptions(CFileItem& item, const std::string& path)
g_directoryCache.ClearDirectory(url.GetWithoutFilename());
}
+namespace
+{
+std::vector<std::string> GetSettingListAsString(const std::string& settingID)
+{
+ std::vector<CVariant> values =
+ CServiceBroker::GetSettingsComponent()->GetSettings()->GetList(settingID);
+ std::vector<std::string> result;
+ std::transform(values.begin(), values.end(), std::back_inserter(result),
+ [](CVariant s) { return s.asString(); });
+ return result;
+}
+
+const std::map<std::string, std::vector<std::string>> artTypeDefaults = {
+ {MediaTypeEpisode, {"thumb"}},
+ {MediaTypeTvShow, {"poster", "fanart", "banner"}},
+ {MediaTypeSeason, {"poster", "fanart", "banner"}},
+ {MediaTypeMovie, {"poster", "fanart"}},
+ {MediaTypeVideoCollection, {"poster", "fanart"}},
+ {MediaTypeMusicVideo, {"poster", "fanart"}},
+ {MediaTypeNone, { "poster", "fanart", "banner", "thumb" }},
+};
+
+const std::vector<std::string> artTypeDefaultsFallback = {};
+
+const std::vector<std::string>& GetArtTypeDefault(const std::string& mediaType)
+{
+ auto defaults = artTypeDefaults.find(mediaType);
+ if (defaults != artTypeDefaults.end())
+ return defaults->second;
+ return artTypeDefaultsFallback;
+}
+
+const std::map<std::string, std::string> artTypeSettings = {
+ {MediaTypeEpisode, CSettings::SETTING_VIDEOLIBRARY_EPISODEART_WHITELIST},
+ {MediaTypeTvShow, CSettings::SETTING_VIDEOLIBRARY_TVSHOWART_WHITELIST},
+ {MediaTypeSeason, CSettings::SETTING_VIDEOLIBRARY_TVSHOWART_WHITELIST},
+ {MediaTypeMovie, CSettings::SETTING_VIDEOLIBRARY_MOVIEART_WHITELIST},
+ {MediaTypeVideoCollection, CSettings::SETTING_VIDEOLIBRARY_MOVIEART_WHITELIST},
+ {MediaTypeMusicVideo, CSettings::SETTING_VIDEOLIBRARY_MUSICVIDEOART_WHITELIST},
+};
+} // namespace
+
std::vector<std::string> CVideoThumbLoader::GetArtTypes(const std::string &type)
{
- const std::shared_ptr<CAdvancedSettings> advancedSettings = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings();
- std::vector<std::string> ret;
- if (type == MediaTypeEpisode)
- {
- ret = {"thumb"};
- for (auto& artType : advancedSettings->m_videoEpisodeExtraArt)
- {
- if (find(ret.begin(), ret.end(), artType) == ret.end())
- ret.push_back(artType);
- }
- }
- else if (type == MediaTypeTvShow)
- {
- ret = {"poster", "fanart", "banner"};
- for (auto& artType : advancedSettings->m_videoTvShowExtraArt)
- {
- if (find(ret.begin(), ret.end(), artType) == ret.end())
- ret.push_back(artType);
- }
- }
- else if (type == MediaTypeSeason)
- {
- ret = {"poster", "fanart", "banner"};
- for (auto& artType : advancedSettings->m_videoTvSeasonExtraArt)
- {
- if (find(ret.begin(), ret.end(), artType) == ret.end())
- ret.push_back(artType);
- }
- }
- else if (type == MediaTypeMovie)
+ int artworkLevel = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
+ CSettings::SETTING_VIDEOLIBRARY_ARTWORK_LEVEL);
+ if (artworkLevel == CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_NONE)
{
- ret = {"poster", "fanart"};
- for (auto& artType : advancedSettings->m_videoMovieExtraArt)
- {
- if (find(ret.begin(), ret.end(), artType) == ret.end())
- ret.push_back(artType);
- }
+ return {};
}
- else if (type == MediaTypeVideoCollection)
+
+ std::vector<std::string> result = GetArtTypeDefault(type);
+ if (artworkLevel != CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_CUSTOM)
{
- ret = {"poster", "fanart"};
- for (auto& artType : advancedSettings->m_videoMovieSetExtraArt)
- {
- if (find(ret.begin(), ret.end(), artType) == ret.end())
- ret.push_back(artType);
- }
+ return result;
}
- else if (type == MediaTypeMusicVideo)
+
+ auto settings = artTypeSettings.find(type);
+ if (settings == artTypeSettings.end())
+ return result;
+
+ for (auto& artType : GetSettingListAsString(settings->second))
{
- ret = {"poster", "fanart"};
- for (auto& artType : advancedSettings->m_videoMusicVideoExtraArt)
- {
- if (find(ret.begin(), ret.end(), artType) == ret.end())
- ret.push_back(artType);
- }
+ if (find(result.begin(), result.end(), artType) == result.end())
+ result.push_back(artType);
}
- else if (type.empty()) // unknown, just the basics
- ret = { "poster", "fanart", "banner", "thumb" };
- return ret;
+ return result;
+}
+
+bool CVideoThumbLoader::IsValidArtType(const std::string& potentialArtType)
+{
+ return !potentialArtType.empty() && potentialArtType.length() <= 25 &&
+ std::find_if_not(
+ potentialArtType.begin(), potentialArtType.end(),
+ StringUtils::isasciialphanum
+ ) == potentialArtType.end();
+}
+
+bool CVideoThumbLoader::IsArtTypeInWhitelist(const std::string& artType, const std::vector<std::string>& whitelist, bool exact)
+{
+ // whitelist contains art "families", 'fanart' also matches 'fanart1', 'fanart2', and so on
+ std::string compareArtType = artType;
+ if (!exact)
+ StringUtils::TrimRight(compareArtType, "0123456789");
+
+ return std::find(whitelist.begin(), whitelist.end(), compareArtType) != whitelist.end();
}
/**
diff --git a/xbmc/video/VideoThumbLoader.h b/xbmc/video/VideoThumbLoader.h
index 96e0a31b49..3c2d9f0453 100644
--- a/xbmc/video/VideoThumbLoader.h
+++ b/xbmc/video/VideoThumbLoader.h
@@ -92,6 +92,10 @@ public:
*/
static std::vector<std::string> GetArtTypes(const std::string &type);
+ static bool IsValidArtType(const std::string& potentialArtType);
+
+ static bool IsArtTypeInWhitelist(const std::string& artType, const std::vector<std::string>& whitelist, bool exact);
+
/*! \brief helper function to retrieve a thumb URL for embedded video thumbs
\param item a video CFileItem.
\return a URL for the embedded thumb.