aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Rector <rmrector@gmail.com>2019-04-06 10:05:12 -0600
committerGitHub <noreply@github.com>2019-04-06 10:05:12 -0600
commit60521a904ba8a8ea4f4f1281c5bbc636549f65b6 (patch)
tree324ca8104a3ed0c940235c6cb6f67d831d8d8ac3
parent4eb34ebe68452821b97befbcc4a8fcb663924f5b (diff)
parentc900963c2a1b395a5e66c0a97f036b8565aace7b (diff)
Merge pull request #15857 from rmrector/fill-video-arttypes
Add available artwork to the video 'Choose art type' dialog
-rw-r--r--xbmc/video/VideoDatabase.cpp111
-rw-r--r--xbmc/video/VideoDatabase.h8
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoInfo.cpp112
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoInfo.h4
4 files changed, 201 insertions, 34 deletions
diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp
index 7c8d0b09ed..1b96904146 100644
--- a/xbmc/video/VideoDatabase.cpp
+++ b/xbmc/video/VideoDatabase.cpp
@@ -4668,6 +4668,117 @@ bool CVideoDatabase::GetArtTypes(const MediaType &mediaType, std::vector<std::st
return false;
}
+namespace
+{
+std::vector<std::string> GetBasicItemAvailableArtTypes(const CVideoInfoTag& tag)
+{
+ std::vector<std::string> result;
+
+ //! @todo artwork: fanart stored separately, doesn't need to be
+ if (tag.m_fanart.GetNumFanarts() && std::find(result.cbegin(), result.cend(), "fanart") == result.cend())
+ result.push_back("fanart");
+
+ // all other images
+ for (const auto& urlEntry : tag.m_strPictureURL.m_url)
+ {
+ std::string artType = urlEntry.m_aspect;
+ if (artType.empty())
+ artType = tag.m_type == MediaTypeEpisode ? "thumb" : "poster";
+ if (urlEntry.m_type == CScraperUrl::URL_TYPE_GENERAL && // exclude season artwork for TV shows
+ !StringUtils::StartsWith(artType, "set.") && // exclude movie set artwork for movies
+ std::find(result.cbegin(), result.cend(), artType) == result.cend())
+ {
+ result.push_back(artType);
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> GetSeasonAvailableArtTypes(int mediaId, CVideoDatabase& db)
+{
+ CVideoInfoTag tag;
+ db.GetSeasonInfo(mediaId, tag);
+
+ std::vector<std::string> result;
+
+ CVideoInfoTag sourceShow;
+ db.GetTvShowInfo("", sourceShow, tag.m_iIdShow);
+ for (const auto& urlEntry : sourceShow.m_strPictureURL.m_url)
+ {
+ std::string artType = urlEntry.m_aspect;
+ if (artType.empty())
+ artType = "poster";
+ if (urlEntry.m_type == CScraperUrl::URL_TYPE_SEASON && urlEntry.m_season == tag.m_iSeason &&
+ std::find(result.cbegin(), result.cend(), artType) == result.cend())
+ {
+ result.push_back(artType);
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> GetMovieSetAvailableArtTypes(int mediaId, CVideoDatabase& db)
+{
+ std::vector<std::string> result;
+ CFileItemList items;
+ std::string baseDir = StringUtils::Format("videodb://movies/sets/%d", mediaId);
+ if (db.GetMoviesNav(baseDir, items))
+ {
+ for (const auto& item : items)
+ {
+ CVideoInfoTag* pTag = item->GetVideoInfoTag();
+ pTag->m_strPictureURL.Parse();
+ //! @todo artwork: fanart stored separately, doesn't need to be
+ pTag->m_fanart.Unpack();
+ if (pTag->m_fanart.GetNumFanarts() &&
+ std::find(result.cbegin(), result.cend(), "fanart") == result.cend())
+ {
+ result.push_back("fanart");
+ }
+
+ // all other images
+ for (const auto& urlEntry : pTag->m_strPictureURL.m_url)
+ {
+ std::string artType = urlEntry.m_aspect;
+ if (artType.empty())
+ artType = "poster";
+ else if (StringUtils::StartsWith(artType, "set."))
+ artType = artType.substr(4);
+
+ if (std::find(result.cbegin(), result.cend(), artType) == result.cend())
+ result.push_back(artType);
+ }
+ }
+ }
+ return result;
+}
+}
+
+std::vector<std::string> CVideoDatabase::GetAvailableArtTypesForItem(int mediaId,
+ const MediaType& mediaType)
+{
+ VIDEODB_CONTENT_TYPE dbType{VIDEODB_CONTENT_UNKNOWN};
+ if (mediaType == MediaTypeTvShow)
+ dbType = VIDEODB_CONTENT_TVSHOWS;
+ else if (mediaType == MediaTypeMovie)
+ dbType = VIDEODB_CONTENT_MOVIES;
+ else if (mediaType == MediaTypeEpisode)
+ dbType = VIDEODB_CONTENT_EPISODES;
+ else if (mediaType == MediaTypeMusicVideo)
+ dbType = VIDEODB_CONTENT_MUSICVIDEOS;
+
+ if (dbType != VIDEODB_CONTENT_UNKNOWN)
+ {
+ CVideoInfoTag tag = GetDetailsByTypeAndId(dbType, mediaId);
+ return GetBasicItemAvailableArtTypes(tag);
+ }
+ if (mediaType == MediaTypeSeason)
+ return GetSeasonAvailableArtTypes(mediaId, *this);
+ if (mediaType == MediaTypeVideoCollection)
+ return GetMovieSetAvailableArtTypes(mediaId, *this);
+ return {};
+}
+
/// \brief GetStackTimes() obtains any saved video times for the stacked file
/// \retval Returns true if the stack times exist, false otherwise.
bool CVideoDatabase::GetStackTimes(const std::string &filePath, std::vector<uint64_t> &times)
diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h
index 5ed2303f45..addc77e798 100644
--- a/xbmc/video/VideoDatabase.h
+++ b/xbmc/video/VideoDatabase.h
@@ -848,6 +848,14 @@ public:
bool GetTvShowSeasonArt(int mediaId, std::map<int, std::map<std::string, std::string> > &seasonArt);
bool GetArtTypes(const MediaType &mediaType, std::vector<std::string> &artTypes);
+ /*! \brief Fetch the distinct types of available-but-unassigned art held in the
+ database for a specific media item.
+ \param mediaId the id in the media table.
+ \param mediaType the type of media, which corresponds to the table the item resides in.
+ \return the types of art e.g. "thumb", "fanart", etc.
+ */
+ std::vector<std::string> GetAvailableArtTypesForItem(int mediaId, const MediaType& mediaType);
+
int AddTag(const std::string &tag);
void AddTagToItem(int idItem, int idTag, const std::string &type);
void RemoveTagFromItem(int idItem, int idTag, const std::string &type);
diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
index 091472544b..14935c1283 100644
--- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
@@ -620,7 +620,73 @@ void CGUIDialogVideoInfo::Play(bool resume)
}
}
-std::string CGUIDialogVideoInfo::ChooseArtType(const CFileItem &videoItem, std::map<std::string, std::string> &currentArt)
+namespace
+{
+// Add art types required in Kodi and configured by the user
+void AddHardCodedAndExtendedArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTag& tag)
+{
+ for (const auto& artType : CVideoThumbLoader::GetArtTypes(tag.m_type))
+ {
+ if (find(artTypes.cbegin(), artTypes.cend(), artType) == artTypes.cend())
+ artTypes.emplace_back(artType);
+ }
+}
+
+// Add art types currently assigned to the media item
+void AddCurrentArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTag& tag,
+ CVideoDatabase& db)
+{
+ std::map<std::string, std::string> currentArt;
+ db.GetArtForItem(tag.m_iDbId, tag.m_type, currentArt);
+ for (const auto& art : currentArt)
+ {
+ if (!art.second.empty() && find(artTypes.cbegin(), artTypes.cend(), art.first) == artTypes.cend())
+ artTypes.push_back(art.first);
+ }
+}
+
+// Add art types that exist for other media items of the same type
+void AddMediaTypeArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTag& tag,
+ CVideoDatabase& db)
+{
+ std::vector<std::string> dbArtTypes;
+ db.GetArtTypes(tag.m_type, dbArtTypes);
+ for (const auto& artType : dbArtTypes)
+ {
+ if (find(artTypes.cbegin(), artTypes.cend(), artType) == artTypes.cend())
+ artTypes.push_back(artType);
+ }
+}
+
+// Add art types from available but unassigned artwork for this media item
+void AddAvailableArtTypes(std::vector<std::string>& artTypes, const CVideoInfoTag& tag,
+ CVideoDatabase& db)
+{
+ for (const auto& artType : db.GetAvailableArtTypesForItem(tag.m_iDbId, tag.m_type))
+ {
+ if (find(artTypes.cbegin(), artTypes.cend(), artType) == artTypes.cend())
+ artTypes.push_back(artType);
+ }
+}
+
+std::vector<std::string> GetArtTypesList(const CVideoInfoTag& tag)
+{
+ CVideoDatabase db;
+ db.Open();
+
+ std::vector<std::string> artTypes;
+
+ AddHardCodedAndExtendedArtTypes(artTypes, tag);
+ AddCurrentArtTypes(artTypes, tag, db);
+ AddMediaTypeArtTypes(artTypes, tag, db);
+ AddAvailableArtTypes(artTypes, tag, db);
+
+ db.Close();
+ return artTypes;
+}
+}
+
+std::string CGUIDialogVideoInfo::ChooseArtType(const CFileItem &videoItem)
{
// prompt for choice
CGUIDialogSelect *dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT);
@@ -633,27 +699,7 @@ std::string CGUIDialogVideoInfo::ChooseArtType(const CFileItem &videoItem, std::
dialog->SetUseDetails(true);
dialog->EnableButton(true, 13516);
- CVideoDatabase db;
- db.Open();
-
- std::vector<std::string> artTypes = CVideoThumbLoader::GetArtTypes(videoItem.GetVideoInfoTag()->m_type);
-
- // add in any stored art for this item that is non-empty.
- db.GetArtForItem(videoItem.GetVideoInfoTag()->m_iDbId, videoItem.GetVideoInfoTag()->m_type, currentArt);
- for (CGUIListItem::ArtMap::iterator i = currentArt.begin(); i != currentArt.end(); ++i)
- {
- if (!i->second.empty() && find(artTypes.begin(), artTypes.end(), i->first) == artTypes.end())
- artTypes.push_back(i->first);
- }
-
- // add any art types that exist for other media items of the same type
- std::vector<std::string> dbArtTypes;
- db.GetArtTypes(videoItem.GetVideoInfoTag()->m_type, dbArtTypes);
- for (std::vector<std::string>::const_iterator it = dbArtTypes.begin(); it != dbArtTypes.end(); ++it)
- {
- if (find(artTypes.begin(), artTypes.end(), *it) == artTypes.end())
- artTypes.push_back(*it);
- }
+ std::vector<std::string> artTypes = GetArtTypesList(*videoItem.GetVideoInfoTag());
for (std::vector<std::string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i)
{
@@ -693,8 +739,7 @@ std::string CGUIDialogVideoInfo::ChooseArtType(const CFileItem &videoItem, std::
void CGUIDialogVideoInfo::OnGetArt()
{
- std::map<std::string, std::string> currentArt;
- std::string type = ChooseArtType(*m_movieItem, currentArt);
+ std::string type = ChooseArtType(*m_movieItem);
if (type.empty())
return; // cancelled
@@ -714,10 +759,10 @@ void CGUIDialogVideoInfo::OnGetArt()
item->SetLabel(g_localizeStrings.Get(13512));
items.Add(item);
}
- else if ((type == "poster" || type == "banner") && currentArt.find("thumb") != currentArt.end())
+ else if ((type == "poster" || type == "banner") && m_movieItem->HasArt("thumb"))
{ // add the 'thumb' type in
CFileItemPtr item(new CFileItem("thumb://Thumb", false));
- item->SetArt("thumb", currentArt["thumb"]);
+ item->SetArt("thumb", m_movieItem->GetArt("thumb"));
item->SetIconImage("DefaultPicture.png");
item->SetLabel(g_localizeStrings.Get(13512));
items.Add(item);
@@ -794,7 +839,7 @@ void CGUIDialogVideoInfo::OnGetArt()
newThumb = thumbs[number];
}
else if (result == "thumb://Thumb")
- newThumb = currentArt["thumb"];
+ newThumb = m_movieItem->GetArt("thumb");
else if (result == "thumb://Local")
newThumb = localThumb;
else if (result == "thumb://Embedded")
@@ -1802,18 +1847,17 @@ bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const CFileItemPtr &item, const
currentThumb = videodb.GetArtForItem(item->GetVideoInfoTag()->m_iDbId, item->GetVideoInfoTag()->m_type, artType);
else
{ // SEASON, SET
- std::map<std::string, std::string> currentArt;
- artType = ChooseArtType(*item, currentArt);
+ artType = ChooseArtType(*item);
if (artType.empty())
return false;
if (artType == "fanart")
return OnGetFanart(item);
- if (currentArt.find(artType) != currentArt.end())
- currentThumb = currentArt[artType];
- else if ((artType == "poster" || artType == "banner") && currentArt.find("thumb") != currentArt.end())
- currentThumb = currentArt["thumb"];
+ if (item->HasArt(artType))
+ currentThumb = item->GetArt(artType);
+ else if ((artType == "poster" || artType == "banner") && item->HasArt("thumb"))
+ currentThumb = item->GetArt("thumb");
}
if (!currentThumb.empty())
@@ -1955,6 +1999,8 @@ bool CGUIDialogVideoInfo::ManageVideoItemArtwork(const CFileItemPtr &item, const
musicdb.SetArtForItem(idArtist, MediaTypeArtist, artType, result);
}
+ item->SetArt(artType, result);
+
CUtil::DeleteVideoDatabaseDirectoryCache();
CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg);
diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.h b/xbmc/video/dialogs/GUIDialogVideoInfo.h
index 0976541b1c..574309d863 100644
--- a/xbmc/video/dialogs/GUIDialogVideoInfo.h
+++ b/xbmc/video/dialogs/GUIDialogVideoInfo.h
@@ -33,7 +33,6 @@ public:
const CFileItemList& CurrentDirectory() const { return *m_castList; };
bool HasListItems() const override { return true; };
- static std::string ChooseArtType(const CFileItem &item, std::map<std::string, std::string> &currentArt);
static void AddItemPathToFileBrowserSources(VECSOURCES &sources, const CFileItem &item);
static int ManageVideoItem(const CFileItemPtr &item);
@@ -103,4 +102,7 @@ protected:
bool m_hasUpdatedThumb = false;
bool m_hasUpdatedUserrating = false;
int m_startUserrating = -1;
+
+private:
+ static std::string ChooseArtType(const CFileItem& item);
};