[Windows] Remove redundant DirectSound error codes
[xbmc.git] / xbmc / video / VideoThumbLoader.cpp
blob87cb6fb2058048bea6ac371abb27175a83c275b5
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "VideoThumbLoader.h"
11 #include "FileItem.h"
12 #include "FileItemList.h"
13 #include "ServiceBroker.h"
14 #include "TextureCache.h"
15 #include "URL.h"
16 #include "cores/VideoPlayer/DVDFileInfo.h"
17 #include "cores/VideoSettings.h"
18 #include "filesystem/Directory.h"
19 #include "filesystem/File.h"
20 #include "filesystem/StackDirectory.h"
21 #include "guilib/GUIComponent.h"
22 #include "guilib/StereoscopicsManager.h"
23 #include "imagefiles/ImageFileURL.h"
24 #include "music/MusicDatabase.h"
25 #include "music/tags/MusicInfoTag.h"
26 #include "network/NetworkFileItemClassify.h"
27 #include "settings/AdvancedSettings.h"
28 #include "settings/SettingUtils.h"
29 #include "settings/Settings.h"
30 #include "settings/SettingsComponent.h"
31 #include "utils/StringUtils.h"
32 #include "utils/URIUtils.h"
33 #include "utils/log.h"
34 #include "video/VideoDatabase.h"
35 #include "video/VideoFileItemClassify.h"
36 #include "video/VideoInfoTag.h"
37 #include "video/VideoManagerTypes.h"
38 #include "video/guilib/VideoVersionHelper.h"
40 #include <algorithm>
41 #include <cstdlib>
42 #include <utility>
44 using namespace KODI;
45 using namespace XFILE;
47 CVideoThumbLoader::CVideoThumbLoader() : CThumbLoader()
49 m_videoDatabase = new CVideoDatabase();
52 CVideoThumbLoader::~CVideoThumbLoader()
54 StopThread();
55 delete m_videoDatabase;
58 void CVideoThumbLoader::OnLoaderStart()
60 m_videoDatabase->Open();
61 m_artCache.clear();
62 CThumbLoader::OnLoaderStart();
65 void CVideoThumbLoader::OnLoaderFinish()
67 m_videoDatabase->Close();
68 m_artCache.clear();
69 CThumbLoader::OnLoaderFinish();
72 namespace
74 std::vector<std::string> GetSettingListAsString(const std::string& settingID)
76 std::vector<CVariant> values =
77 CServiceBroker::GetSettingsComponent()->GetSettings()->GetList(settingID);
78 std::vector<std::string> result;
79 std::transform(values.begin(), values.end(), std::back_inserter(result),
80 [](const CVariant& s) { return s.asString(); });
81 return result;
84 const std::map<std::string, std::vector<std::string>> artTypeDefaults = {
85 {MediaTypeEpisode, {"thumb"}},
86 {MediaTypeTvShow, {"poster", "fanart", "banner"}},
87 {MediaTypeSeason, {"poster", "fanart", "banner"}},
88 {MediaTypeMovie, {"poster", "fanart"}},
89 {MediaTypeVideoCollection, {"poster", "fanart"}},
90 {MediaTypeMusicVideo, {"poster", "fanart"}},
91 {MediaTypeVideoVersion, {"poster", "fanart", "banner", "thumb"}},
92 {MediaTypeNone, {"poster", "fanart", "banner", "thumb"}},
95 const std::vector<std::string> artTypeDefaultsFallback = {};
97 const std::vector<std::string>& GetArtTypeDefault(const std::string& mediaType)
99 auto defaults = artTypeDefaults.find(mediaType);
100 if (defaults != artTypeDefaults.end())
101 return defaults->second;
102 return artTypeDefaultsFallback;
105 const std::map<std::string, std::string> artTypeSettings = {
106 {MediaTypeEpisode, CSettings::SETTING_VIDEOLIBRARY_EPISODEART_WHITELIST},
107 {MediaTypeTvShow, CSettings::SETTING_VIDEOLIBRARY_TVSHOWART_WHITELIST},
108 {MediaTypeSeason, CSettings::SETTING_VIDEOLIBRARY_TVSHOWART_WHITELIST},
109 {MediaTypeMovie, CSettings::SETTING_VIDEOLIBRARY_MOVIEART_WHITELIST},
110 {MediaTypeVideoCollection, CSettings::SETTING_VIDEOLIBRARY_MOVIEART_WHITELIST},
111 {MediaTypeMusicVideo, CSettings::SETTING_VIDEOLIBRARY_MUSICVIDEOART_WHITELIST},
112 {MediaTypeVideoVersion, CSettings::SETTING_VIDEOLIBRARY_MOVIEART_WHITELIST},
114 } // namespace
116 std::vector<std::string> CVideoThumbLoader::GetArtTypes(const std::string &type)
118 int artworkLevel = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
119 CSettings::SETTING_VIDEOLIBRARY_ARTWORK_LEVEL);
120 if (artworkLevel == CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_NONE)
122 return {};
125 std::vector<std::string> result = GetArtTypeDefault(type);
126 if (artworkLevel != CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_CUSTOM)
128 return result;
131 auto settings = artTypeSettings.find(type);
132 if (settings == artTypeSettings.end())
133 return result;
135 for (auto& artType : GetSettingListAsString(settings->second))
137 if (find(result.begin(), result.end(), artType) == result.end())
138 result.push_back(artType);
141 return result;
144 bool CVideoThumbLoader::IsValidArtType(const std::string& potentialArtType)
146 return !potentialArtType.empty() && potentialArtType.length() <= 25 &&
147 std::find_if_not(
148 potentialArtType.begin(), potentialArtType.end(),
149 StringUtils::isasciialphanum
150 ) == potentialArtType.end();
153 bool CVideoThumbLoader::IsArtTypeInWhitelist(const std::string& artType, const std::vector<std::string>& whitelist, bool exact)
155 // whitelist contains art "families", 'fanart' also matches 'fanart1', 'fanart2', and so on
156 std::string compareArtType = artType;
157 if (!exact)
158 StringUtils::TrimRight(compareArtType, "0123456789");
160 return std::find(whitelist.begin(), whitelist.end(), compareArtType) != whitelist.end();
164 * Look for a thumbnail for pItem. If one does not exist, look for an autogenerated
165 * thumbnail. If that does not exist, attempt to autogenerate one. Finally, check
166 * for the existence of fanart and set properties accordingly.
167 * @return: true if pItem has been modified
169 bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
171 bool result = LoadItemCached(pItem);
172 result |= LoadItemLookup(pItem);
174 return result;
177 bool CVideoThumbLoader::LoadItemCached(CFileItem* pItem)
179 if (pItem->m_bIsShareOrDrive
180 || pItem->IsParentFolder())
181 return false;
183 m_videoDatabase->Open();
185 if (!pItem->HasVideoInfoTag() || !pItem->GetVideoInfoTag()->HasStreamDetails()) // no stream details
187 if ((pItem->HasVideoInfoTag() &&
188 pItem->GetVideoInfoTag()->m_iFileId >= 0) // file (or maybe folder) is in the database
189 || (!pItem->m_bIsFolder &&
190 VIDEO::IsVideo(
191 *pItem))) // Some other video file for which we haven't yet got any database details
193 if (m_videoDatabase->GetStreamDetails(*pItem))
194 pItem->SetInvalid();
198 // video db items normally have info in the database
199 if (pItem->HasVideoInfoTag() && !pItem->GetProperty("libraryartfilled").asBoolean())
201 FillLibraryArt(*pItem);
203 if (!pItem->GetVideoInfoTag()->m_type.empty() &&
204 pItem->GetVideoInfoTag()->m_type != MediaTypeMovie &&
205 pItem->GetVideoInfoTag()->m_type != MediaTypeTvShow &&
206 pItem->GetVideoInfoTag()->m_type != MediaTypeEpisode &&
207 pItem->GetVideoInfoTag()->m_type != MediaTypeMusicVideo &&
208 pItem->GetVideoInfoTag()->m_type != MediaTypeVideoVersion)
210 m_videoDatabase->Close();
211 return true; // nothing else to be done
215 // if we have no art, look for it all
216 std::map<std::string, std::string> artwork = pItem->GetArt();
217 if (artwork.empty())
219 std::vector<std::string> artTypes = GetArtTypes(pItem->HasVideoInfoTag() ? pItem->GetVideoInfoTag()->m_type : "");
220 if (find(artTypes.begin(), artTypes.end(), "thumb") == artTypes.end())
221 artTypes.emplace_back("thumb"); // always look for "thumb" art for files
222 for (std::vector<std::string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i)
224 std::string type = *i;
225 std::string art = GetCachedImage(*pItem, type);
226 if (!art.empty())
227 artwork.insert(std::make_pair(type, art));
229 pItem->AppendArt(artwork);
232 m_videoDatabase->Close();
234 return true;
237 bool CVideoThumbLoader::LoadItemLookup(CFileItem* pItem)
239 if (pItem->m_bIsShareOrDrive || pItem->IsParentFolder() || pItem->GetPath() == "add")
240 return false;
242 if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->m_type.empty() &&
243 pItem->GetVideoInfoTag()->m_type != MediaTypeMovie &&
244 pItem->GetVideoInfoTag()->m_type != MediaTypeTvShow &&
245 pItem->GetVideoInfoTag()->m_type != MediaTypeEpisode &&
246 pItem->GetVideoInfoTag()->m_type != MediaTypeMusicVideo &&
247 pItem->GetVideoInfoTag()->m_type != MediaTypeVideoVersion)
248 return false; // Nothing to do here
250 m_videoDatabase->Open();
252 const bool isLibraryItem = pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_iDbId > -1 &&
253 !pItem->GetVideoInfoTag()->m_type.empty();
254 const bool libraryArtFilled =
255 pItem->HasVideoInfoTag() && pItem->GetProperty("libraryartfilled").asBoolean();
256 if (!isLibraryItem || !libraryArtFilled)
258 std::map<std::string, std::string> artwork = pItem->GetArt();
259 std::vector<std::string> artTypes =
260 GetArtTypes(pItem->HasVideoInfoTag() ? pItem->GetVideoInfoTag()->m_type : "");
261 if (find(artTypes.begin(), artTypes.end(), "thumb") == artTypes.end())
262 artTypes.emplace_back("thumb"); // always look for "thumb" art for files
263 for (std::vector<std::string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i)
265 std::string type = *i;
266 if (!pItem->HasArt(type))
268 std::string art = GetLocalArt(*pItem, type, type == "fanart");
269 if (!art.empty()) // cache it
271 SetCachedImage(*pItem, type, art);
272 CServiceBroker::GetTextureCache()->BackgroundCacheImage(art);
273 artwork.insert(std::make_pair(type, art));
275 else
277 // If nothing was found, try embedded art
278 if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->m_coverArt.empty())
280 for (auto& it : pItem->GetVideoInfoTag()->m_coverArt)
282 if (it.m_type == type)
284 art = IMAGE_FILES::URLFromFile(pItem->GetPath(), "video_" + type);
285 artwork.insert(std::make_pair(type, art));
292 pItem->AppendArt(artwork);
295 // We can only extract flags/thumbs for file-like items
296 if (!pItem->m_bIsFolder && VIDEO::IsVideo(*pItem))
298 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
299 if (!pItem->HasArt("thumb"))
301 std::string thumbURL = GetEmbeddedThumbURL(*pItem);
302 if (CDVDFileInfo::CanExtract(*pItem) &&
303 settings->GetBool(CSettings::SETTING_MYVIDEOS_EXTRACTTHUMB) &&
304 settings->GetInt(CSettings::SETTING_VIDEOLIBRARY_ARTWORK_LEVEL) !=
305 CSettings::VIDEOLIBRARY_ARTWORK_LEVEL_NONE)
307 pItem->SetArt("thumb", thumbURL);
309 if (pItem->HasVideoInfoTag())
311 CVideoInfoTag* info = pItem->GetVideoInfoTag();
312 if (info->m_iDbId > 0 && !info->m_type.empty())
313 m_videoDatabase->SetArtForItem(info->m_iDbId, info->m_type, "thumb", thumbURL);
318 // flag extraction mostly for non-library items - should end up somewhere else,
319 // like a VideoInfoLoader if it existed
320 if (settings->GetBool(CSettings::SETTING_MYVIDEOS_EXTRACTFLAGS) &&
321 CDVDFileInfo::CanExtract(*pItem) &&
322 (!pItem->HasVideoInfoTag() || !pItem->GetVideoInfoTag()->HasStreamDetails()))
324 // No tag or no details set, so extract them
325 CLog::LogF(LOGDEBUG, "trying to extract filestream details from video file {}",
326 CURL::GetRedacted(pItem->GetPath()));
327 if (CDVDFileInfo::GetFileStreamDetails(pItem))
329 CVideoInfoTag* info = pItem->GetVideoInfoTag();
330 m_videoDatabase->BeginTransaction();
332 if (info->m_iFileId < 0)
333 m_videoDatabase->SetStreamDetailsForFile(
334 info->m_streamDetails,
335 !info->m_strFileNameAndPath.empty() ? info->m_strFileNameAndPath : pItem->GetPath());
336 else
337 m_videoDatabase->SetStreamDetailsForFileId(info->m_streamDetails, info->m_iFileId);
339 // overwrite the runtime value if the one from streamdetails is available
340 if (info->m_iDbId > 0 && info->GetStaticDuration() != info->GetDuration())
342 info->SetDuration(info->GetDuration());
344 // store the updated information in the database
345 m_videoDatabase->SetDetailsForItem(info->m_iDbId, info->m_type, *info, pItem->GetArt());
348 m_videoDatabase->CommitTransaction();
352 DetectAndAddMissingItemData(*pItem);
354 m_videoDatabase->Close();
355 return true;
358 bool CVideoThumbLoader::FillLibraryArt(CFileItem &item)
360 CVideoInfoTag &tag = *item.GetVideoInfoTag();
361 std::map<std::string, std::string> artwork;
362 // Video item can be an album - either a
363 // a) search result with full details including music library album id, or
364 // b) musicvideo album that needs matching to a music album, storing id as well as fetch art.
365 if (tag.m_type == MediaTypeAlbum)
367 int idAlbum = -1;
368 if (item.HasMusicInfoTag()) // Album is a search result
369 idAlbum = item.GetMusicInfoTag()->GetAlbumId();
370 CMusicDatabase database;
371 database.Open();
372 if (idAlbum < 0 && !tag.m_strAlbum.empty() &&
373 item.GetProperty("musicvideomediatype") == MediaTypeAlbum)
375 // Musicvideo album - try to match album in music db on artist(s) and album name.
376 // Get review if available and save the matching music library album id.
377 std::string strArtist = StringUtils::Join(
378 tag.m_artist,
379 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
380 std::string strReview;
381 if (database.GetMatchingMusicVideoAlbum(
382 tag.m_strAlbum, strArtist, idAlbum, strReview))
384 item.SetProperty("album_musicid", idAlbum);
385 item.SetProperty("album_description", strReview);
388 // Get album art only (not related artist art)
389 if (database.GetArtForItem(idAlbum, MediaTypeAlbum, artwork))
390 item.SetArt(artwork);
391 database.Close();
393 else if (tag.m_type == "actor" && !tag.m_artist.empty() &&
394 item.GetProperty("musicvideomediatype") == MediaTypeArtist)
396 // Try to match artist in music db on name, get bio if available and fetch artist art
397 // Save the matching music library artist id.
398 CMusicDatabase database;
399 database.Open();
400 CArtist artist;
401 int idArtist = database.GetArtistByName(tag.m_artist[0]);
402 if (idArtist > 0)
404 database.GetArtist(idArtist, artist);
405 tag.m_strPlot = artist.strBiography;
406 item.SetProperty("artist_musicid", idArtist);
408 if (database.GetArtForItem(idArtist, MediaTypeArtist, artwork))
409 item.SetArt(artwork);
410 database.Close();
413 if (tag.m_iDbId > -1 && !tag.m_type.empty())
415 m_videoDatabase->Open();
417 // @todo unify asset path for other items path
418 if (VIDEO::IsVideoAssetFile(item))
420 if (m_videoDatabase->GetArtForAsset(
421 tag.m_iFileId,
422 (item.GetProperty("noartfallbacktoowner").asBoolean(false) ||
423 item.GetVideoInfoTag()->GetAssetInfo().GetType() != VideoAssetType::VERSION)
424 ? ArtFallbackOptions::NONE
425 : ArtFallbackOptions::PARENT,
426 artwork))
427 item.AppendArt(artwork);
429 else if (m_videoDatabase->GetArtForItem(tag.m_iDbId, tag.m_type, artwork))
431 item.AppendArt(artwork);
433 else if (tag.m_type == "actor" && !tag.m_artist.empty() &&
434 item.GetProperty("musicvideomediatype") != MediaTypeArtist)
436 // Fallback to music library for actors without art
437 //! @todo Is m_artist set other than musicvideo? Remove this fallback if not.
438 CMusicDatabase database;
439 database.Open();
440 int idArtist = database.GetArtistByName(item.GetLabel());
441 if (database.GetArtForItem(idArtist, MediaTypeArtist, artwork))
442 item.SetArt(artwork);
443 database.Close();
446 if (tag.m_type == MediaTypeEpisode || tag.m_type == MediaTypeSeason)
448 // For episodes and seasons, we want to set fanart for that of the show
449 if (!item.HasArt("tvshow.fanart") && tag.m_iIdShow >= 0)
451 const ArtMap& artmap = GetArtFromCache(MediaTypeTvShow, tag.m_iIdShow);
452 if (!artmap.empty())
454 item.AppendArt(artmap, MediaTypeTvShow);
455 item.SetArtFallback("fanart", "tvshow.fanart");
456 item.SetArtFallback("tvshow.thumb", "tvshow.poster");
460 if (tag.m_type == MediaTypeEpisode && !item.HasArt("season.poster") && tag.m_iSeason > -1)
462 const ArtMap& artmap = GetArtFromCache(MediaTypeSeason, tag.m_iIdSeason);
463 if (!artmap.empty())
464 item.AppendArt(artmap, MediaTypeSeason);
467 else if (tag.m_type == MediaTypeMovie && tag.m_set.id >= 0 && !item.HasArt("set.fanart"))
469 const ArtMap& artmap = GetArtFromCache(MediaTypeVideoCollection, tag.m_set.id);
470 if (!artmap.empty())
471 item.AppendArt(artmap, MediaTypeVideoCollection);
473 m_videoDatabase->Close();
475 item.SetProperty("libraryartfilled", true);
476 return !item.GetArt().empty();
479 bool CVideoThumbLoader::FillThumb(CFileItem &item)
481 if (item.HasArt("thumb"))
482 return true;
483 std::string thumb = GetCachedImage(item, "thumb");
484 if (thumb.empty())
486 thumb = GetLocalArt(item, "thumb");
487 if (!thumb.empty())
488 SetCachedImage(item, "thumb", thumb);
490 if (!thumb.empty())
491 item.SetArt("thumb", thumb);
492 else
494 // If nothing was found, try embedded art
495 if (item.HasVideoInfoTag() && !item.GetVideoInfoTag()->m_coverArt.empty())
497 for (auto& it : item.GetVideoInfoTag()->m_coverArt)
499 if (it.m_type == "thumb")
501 thumb = IMAGE_FILES::URLFromFile(item.GetPath(), "video_" + it.m_type);
502 item.SetArt(it.m_type, thumb);
508 return !thumb.empty();
511 std::string CVideoThumbLoader::GetLocalArt(const CFileItem &item, const std::string &type, bool checkFolder)
513 if (item.SkipLocalArt())
514 return "";
516 /* Cache directory for (sub) folders with Curl("streamed") filesystems. We need to do this
517 else entering (new) directories from the app thread becomes much slower. This
518 is caused by the fact that Curl Stat/Exist() is really slow and that the
519 thumbloader thread accesses the streamed filesystem at the same time as the
520 app thread and the latter has to wait for it.
523 const auto settings = CServiceBroker::GetSettingsComponent()->GetSettings();
525 const bool cacheAll =
526 settings ? settings->GetInt(CSettings::SETTING_FILECACHE_BUFFERMODE) == CACHE_BUFFER_MODE_ALL
527 : false;
529 if (item.m_bIsFolder && (NETWORK::IsStreamedFilesystem(item) || cacheAll))
531 CFileItemList items; // Dummy list
532 CDirectory::GetDirectory(item.GetPath(), items, "", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_READ_CACHE | DIR_FLAG_NO_FILE_INFO);
535 std::string art;
536 if (!type.empty())
538 art = item.FindLocalArt(type + ".jpg", checkFolder);
539 if (art.empty())
540 art = item.FindLocalArt(type + ".png", checkFolder);
542 if (art.empty() && (type.empty() || type == "thumb"))
543 { // backward compatibility
544 art = item.FindLocalArt("", false);
545 if (art.empty() && (checkFolder || (item.m_bIsFolder && !item.IsFileFolder()) || item.IsOpticalMediaFile()))
546 { // try movie.tbn
547 art = item.FindLocalArt("movie.tbn", true);
548 if (art.empty()) // try folder.jpg
549 art = item.FindLocalArt("folder.jpg", true);
553 return art;
556 std::string CVideoThumbLoader::GetEmbeddedThumbURL(const CFileItem &item)
558 std::string path(item.GetPath());
559 if (VIDEO::IsVideoDb(item) && item.HasVideoInfoTag())
560 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
561 if (URIUtils::IsStack(path))
562 path = CStackDirectory::GetFirstStackedFile(path);
564 return IMAGE_FILES::URLFromFile(path, "video");
567 void CVideoThumbLoader::DetectAndAddMissingItemData(CFileItem &item)
569 // @todo remove exception for hybrid movie/folder of versions
570 if (item.m_bIsFolder && !StringUtils::StartsWith(item.GetPath(), VIDEODB_PATH_VERSION_ID_ALL))
571 return;
573 if (item.HasVideoInfoTag())
575 CStreamDetails& details = item.GetVideoInfoTag()->m_streamDetails;
577 // add audio language properties
578 for (int i = 1; i <= details.GetAudioStreamCount(); i++)
580 std::string index = std::to_string(i);
581 item.SetProperty("AudioChannels." + index, details.GetAudioChannels(i));
582 item.SetProperty("AudioCodec." + index, details.GetAudioCodec(i).c_str());
583 item.SetProperty("AudioLanguage." + index, details.GetAudioLanguage(i).c_str());
586 // add subtitle language properties
587 for (int i = 1; i <= details.GetSubtitleStreamCount(); i++)
589 std::string index = std::to_string(i);
590 item.SetProperty("SubtitleLanguage." + index, details.GetSubtitleLanguage(i).c_str());
594 const CStereoscopicsManager &stereoscopicsManager = CServiceBroker::GetGUI()->GetStereoscopicsManager();
596 std::string stereoMode;
598 // detect stereomode for videos
599 if (item.HasVideoInfoTag())
600 stereoMode = item.GetVideoInfoTag()->m_streamDetails.GetStereoMode();
602 if (stereoMode.empty())
604 std::string path = item.GetPath();
605 if (VIDEO::IsVideoDb(item) && item.HasVideoInfoTag())
606 path = item.GetVideoInfoTag()->GetPath();
608 // check for custom stereomode setting in video settings
609 CVideoSettings itemVideoSettings;
610 m_videoDatabase->Open();
611 if (m_videoDatabase->GetVideoSettings(item, itemVideoSettings) && itemVideoSettings.m_StereoMode != RENDER_STEREO_MODE_OFF)
613 stereoMode = CStereoscopicsManager::ConvertGuiStereoModeToString(static_cast<RENDER_STEREO_MODE>(itemVideoSettings.m_StereoMode));
615 m_videoDatabase->Close();
617 // still empty, try grabbing from filename
618 //! @todo in case of too many false positives due to using the full path, extract the filename only using string utils
619 if (stereoMode.empty())
620 stereoMode = stereoscopicsManager.DetectStereoModeByString(path);
623 if (!stereoMode.empty())
624 item.SetProperty("stereomode", CStereoscopicsManager::NormalizeStereoMode(stereoMode));
627 const ArtMap& CVideoThumbLoader::GetArtFromCache(const std::string &mediaType, const int id)
629 std::pair<MediaType, int> key = std::make_pair(mediaType, id);
630 auto it = m_artCache.find(key);
631 if (it == m_artCache.end())
633 ArtMap newart;
634 m_videoDatabase->GetArtForItem(id, mediaType, newart);
635 it = m_artCache.insert(std::make_pair(key, std::move(newart))).first;
637 return it->second;