Permalink
Browse files

[videodb][infomanager] Add support for overview (plot) in movie sets.

Makes it possible to specify an overview/plot in movies sets.
Skins can retrieve it via ListItem.Plot (in fact Confluence doesn't need any
modification - "set overview" will be shown where the plot for movies is).

This changes the format of the <set> tag for movie NFO files.
Current:
  <set>My movie set</set>
Proposed:
  <set>
    <name>My movie set</name>
    <overview>This is my awesome movie set.</overview>
  </set>
The <overview> tag is optional, and the current format will still be supported
to not break existing scrapers or local NFO files.

See:
  * http://forum.kodi.tv/showthread.php?tid=237761
  * https://www.themoviedb.org/collection/121938-the-hobbit-collection
    (API does provide the "overview".)
  • Loading branch information...
menakite committed Sep 9, 2015
1 parent 9f3e337 commit 8cf9ecd92effe8b0003a900ff89c42662387f505
@@ -5298,7 +5298,7 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std::
return item->GetPVRTimerInfoTag()->GetEpgInfoTag()->Plot();
if (item->HasVideoInfoTag())
{
if (item->GetVideoInfoTag()->m_type != MediaTypeTvShow)
if (item->GetVideoInfoTag()->m_type != MediaTypeTvShow && item->GetVideoInfoTag()->m_type != MediaTypeVideoCollection)
if (item->GetVideoInfoTag()->m_playCount == 0 && !CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOLIBRARY_SHOWUNWATCHEDPLOTS))
return g_localizeStrings.Get(20370);

@@ -98,6 +98,7 @@ bool GroupUtils::Group(GroupBy groupBy, const std::string &baseDir, const CFileI
CVideoInfoTag* setInfo = pItem->GetVideoInfoTag();
setInfo->m_strPath = pItem->GetPath();
setInfo->m_strTitle = pItem->GetLabel();
setInfo->m_strPlot = (*set->second.begin())->GetVideoInfoTag()->m_strSetOverview;

int ratings = 0;
int iWatched = 0; // have all the movies been played at least once?
@@ -187,8 +187,8 @@ void CVideoDatabase::CreateTables()
"strVideoCodec text, fVideoAspect float, iVideoWidth integer, iVideoHeight integer, "
"strAudioCodec text, iAudioChannels integer, strAudioLanguage text, strSubtitleLanguage text, iVideoDuration integer, strStereoMode text)");

CLog::Log(LOGINFO, "create sets table");
m_pDS->exec("CREATE TABLE sets ( idSet integer primary key, strSet text)\n");
CLog::Log(LOGINFO, "create sets table");
m_pDS->exec("CREATE TABLE sets ( idSet integer primary key, strSet text, strOverview text)");

CLog::Log(LOGINFO, "create seasons table");
m_pDS->exec("CREATE TABLE seasons ( idSeason integer primary key, idShow integer, season integer)");
@@ -447,6 +447,7 @@ void CVideoDatabase::CreateViews()
m_pDS->exec("CREATE VIEW movie_view AS SELECT"
" movie.*,"
" sets.strSet AS strSet,"
" sets.strOverview AS strSetOverview,"
" files.strFileName AS strFileName,"
" path.strPath AS strPath,"
" files.playCount AS playCount,"
@@ -1385,12 +1386,39 @@ int CVideoDatabase::AddToTable(const std::string& table, const std::string& firs
return -1;
}

int CVideoDatabase::AddSet(const std::string& strSet)
int CVideoDatabase::AddSet(const std::string& strSet, const std::string& strOverview /* = "" */)
{
if (strSet.empty())
return -1;

return AddToTable("sets", "idSet", "strSet", strSet);
try
{
if (m_pDB.get() == nullptr || m_pDS.get() == nullptr)
return -1;

std::string strSQL = PrepareSQL("SELECT idSet FROM sets WHERE strSet LIKE '%s'", strSet.c_str());
m_pDS->query(strSQL);
if (m_pDS->num_rows() == 0)
{
m_pDS->close();
strSQL = PrepareSQL("INSERT INTO sets (idSet, strSet, strOverview) VALUES(NULL, '%s', '%s')", strSet.c_str(), strOverview.c_str());
m_pDS->exec(strSQL);
int id = static_cast<int>(m_pDS->lastinsertid());
return id;
}
else
{
int id = m_pDS->fv("idSet").get_asInt();
m_pDS->close();
return id;
}
}
catch (...)
{
CLog::Log(LOGERROR, "%s (%s) failed", __FUNCTION__, strSet.c_str());
}

return -1;
}

int CVideoDatabase::AddTag(const std::string& name)
@@ -2066,7 +2094,7 @@ int CVideoDatabase::SetDetailsForMovie(const std::string& strFilenameAndPath, co
int idSet = -1;
if (!details.m_strSet.empty())
{
idSet = AddSet(details.m_strSet);
idSet = AddSet(details.m_strSet, details.m_strSetOverview);
// add art if not available
std::map<std::string, std::string> setArt;
if (!GetArtForItem(idSet, MediaTypeVideoCollection, setArt))
@@ -2158,7 +2186,7 @@ int CVideoDatabase::UpdateDetailsForMovie(int idMovie, const CVideoInfoTag& deta
idSet = -1;
if (!details.m_strSet.empty())
{
idSet = AddSet(details.m_strSet);
idSet = AddSet(details.m_strSet, details.m_strSetOverview);
// add art if not available
std::map<std::string, std::string> setArt;
if (!GetArtForItem(idSet, "set", setArt))
@@ -2223,7 +2251,7 @@ int CVideoDatabase::SetDetailsForMovieSet(const CVideoInfoTag& details, const st
BeginTransaction();
if (idSet < 0)
{
idSet = AddSet(details.m_strTitle);
idSet = AddSet(details.m_strTitle, details.m_strPlot);
if (idSet < 0)
{
RollbackTransaction();
@@ -2234,7 +2262,7 @@ int CVideoDatabase::SetDetailsForMovieSet(const CVideoInfoTag& details, const st
SetArtForItem(idSet, MediaTypeVideoCollection, artwork);

// and insert the new row
std::string sql = PrepareSQL("UPDATE sets SET strSet='%s' WHERE idSet=%i", details.m_strTitle.c_str(), idSet);
std::string sql = PrepareSQL("UPDATE sets SET strSet='%s', strOverview='%s' WHERE idSet=%i", details.m_strTitle.c_str(), details.m_strPlot.c_str(), idSet);
m_pDS->exec(sql);
CommitTransaction();

@@ -3479,6 +3507,7 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons

details.m_iSetId = record->at(VIDEODB_DETAILS_MOVIE_SET_ID).get_asInt();
details.m_strSet = record->at(VIDEODB_DETAILS_MOVIE_SET_NAME).get_asString();
details.m_strSetOverview = record->at(VIDEODB_DETAILS_MOVIE_SET_OVERVIEW).get_asString();
details.m_iFileId = record->at(VIDEODB_DETAILS_FILEID).get_asInt();
details.m_strPath = record->at(VIDEODB_DETAILS_MOVIE_PATH).get_asString();
std::string strFileName = record->at(VIDEODB_DETAILS_MOVIE_FILE).get_asString();
@@ -4602,11 +4631,14 @@ void CVideoDatabase::UpdateTables(int iVersion)
m_pDS->exec("ALTER TABLE tvshow ADD userrating integer");
m_pDS->exec("ALTER TABLE musicvideo ADD userrating integer");
}

if (iVersion < 97)
m_pDS->exec("ALTER TABLE sets ADD strOverview TEXT");
}

int CVideoDatabase::GetSchemaVersion() const
{
return 96;
return 97;
}

bool CVideoDatabase::LookupByFolders(const std::string &path, bool shows)
@@ -75,13 +75,14 @@ namespace VIDEO
#define VIDEODB_DETAILS_MOVIE_SET_ID VIDEODB_MAX_COLUMNS + 2
#define VIDEODB_DETAILS_MOVIE_USER_RATING VIDEODB_MAX_COLUMNS + 3
#define VIDEODB_DETAILS_MOVIE_SET_NAME VIDEODB_MAX_COLUMNS + 4
#define VIDEODB_DETAILS_MOVIE_FILE VIDEODB_MAX_COLUMNS + 5
#define VIDEODB_DETAILS_MOVIE_PATH VIDEODB_MAX_COLUMNS + 6
#define VIDEODB_DETAILS_MOVIE_PLAYCOUNT VIDEODB_MAX_COLUMNS + 7
#define VIDEODB_DETAILS_MOVIE_LASTPLAYED VIDEODB_MAX_COLUMNS + 8
#define VIDEODB_DETAILS_MOVIE_DATEADDED VIDEODB_MAX_COLUMNS + 9
#define VIDEODB_DETAILS_MOVIE_RESUME_TIME VIDEODB_MAX_COLUMNS + 10
#define VIDEODB_DETAILS_MOVIE_TOTAL_TIME VIDEODB_MAX_COLUMNS + 11
#define VIDEODB_DETAILS_MOVIE_SET_OVERVIEW VIDEODB_MAX_COLUMNS + 5
#define VIDEODB_DETAILS_MOVIE_FILE VIDEODB_MAX_COLUMNS + 6
#define VIDEODB_DETAILS_MOVIE_PATH VIDEODB_MAX_COLUMNS + 7
#define VIDEODB_DETAILS_MOVIE_PLAYCOUNT VIDEODB_MAX_COLUMNS + 8
#define VIDEODB_DETAILS_MOVIE_LASTPLAYED VIDEODB_MAX_COLUMNS + 9
#define VIDEODB_DETAILS_MOVIE_DATEADDED VIDEODB_MAX_COLUMNS + 10
#define VIDEODB_DETAILS_MOVIE_RESUME_TIME VIDEODB_MAX_COLUMNS + 11
#define VIDEODB_DETAILS_MOVIE_TOTAL_TIME VIDEODB_MAX_COLUMNS + 12

#define VIDEODB_DETAILS_EPISODE_TVSHOW_ID VIDEODB_MAX_COLUMNS + 2
#define VIDEODB_DETAILS_EPISODE_USER_RATING VIDEODB_MAX_COLUMNS + 3
@@ -797,7 +798,7 @@ class CVideoDatabase : public CDatabase
virtual bool GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription &sorting);

int AddSeason(int showID, int season);
int AddSet(const std::string& strSet);
int AddSet(const std::string& strSet, const std::string& strOverview = "");
void ClearMovieSet(int idMovie);
void SetMovieSet(int idMovie, int idSet);
bool SetVideoUserRating(int dbId, int rating, const MediaType& mediaType);
@@ -51,6 +51,7 @@ void CVideoInfoTag::Reset()
m_cast.clear();
m_strSet.clear();
m_iSetId = -1;
m_strSetOverview.clear();
m_tags.clear();
m_strFile.clear();
m_strPath.clear();
@@ -175,7 +176,14 @@ bool CVideoInfoTag::Save(TiXmlNode *node, const std::string &tag, bool savePathI
XMLUtils::SetString(movie, "id", m_strIMDBNumber);
XMLUtils::SetStringArray(movie, "genre", m_genre);
XMLUtils::SetStringArray(movie, "country", m_country);
XMLUtils::SetString(movie, "set", m_strSet);
if (!m_strSet.empty())
{
TiXmlElement set("set");
XMLUtils::SetString(&set, "name", m_strSet);
if (!m_strSetOverview.empty())
XMLUtils::SetString(&set, "overview", m_strSetOverview);
movie->InsertEndChild(set);
}
XMLUtils::SetStringArray(movie, "tag", m_tags);
XMLUtils::SetStringArray(movie, "credits", m_writingCredits);
XMLUtils::SetStringArray(movie, "director", m_director);
@@ -288,6 +296,7 @@ void CVideoInfoTag::Archive(CArchive& ar)

ar << m_strSet;
ar << m_iSetId;
ar << m_strSetOverview;
ar << m_tags;
ar << m_duration;
ar << m_strFile;
@@ -366,6 +375,7 @@ void CVideoInfoTag::Archive(CArchive& ar)

ar >> m_strSet;
ar >> m_iSetId;
ar >> m_strSetOverview;
ar >> m_tags;
ar >> m_duration;
ar >> m_strFile;
@@ -440,6 +450,7 @@ void CVideoInfoTag::Serialize(CVariant& value) const
}
value["set"] = m_strSet;
value["setid"] = m_iSetId;
value["setoverview"] = m_strSetOverview;
value["tag"] = m_tags;
value["runtime"] = GetDuration();
value["file"] = m_strFile;
@@ -746,8 +757,23 @@ void CVideoInfoTag::ParseNative(const TiXmlElement* movie, bool prioritise)
node = node->NextSiblingElement("actor");
}

// Pre-Jarvis NFO file:
// <set>A set</set>
if (XMLUtils::GetString(movie, "set", value))
SetSet(value);
// Jarvis+:
// <set><name>A set</name><overview>A set with a number of movies...</overview></set>
node = movie->FirstChildElement("set");
if (node)
{
// No name, no set
if (XMLUtils::GetString(node, "name", value))
{
SetSet(value);
if (XMLUtils::GetString(node, "overview", value))
SetSetOverview(value);
}
}

std::vector<std::string> tags(m_tags);
if (XMLUtils::GetStringArray(movie, "tag", tags, prioritise, g_advancedSettings.m_videoItemSeparator))
@@ -987,6 +1013,11 @@ void CVideoInfoTag::SetSet(std::string set)
m_strSet = Trim(std::move(set));
}

void CVideoInfoTag::SetSetOverview(std::string setOverview)
{
m_strSetOverview = Trim(std::move(setOverview));
}

void CVideoInfoTag::SetTags(std::vector<std::string> tags)
{
m_tags = Trim(std::move(tags));
@@ -109,6 +109,7 @@ class CVideoInfoTag : public IArchivable, public ISerializable, public ISortable
void SetVotes(std::string votes);
void SetArtist(std::vector<std::string> artist);
void SetSet(std::string set);
void SetSetOverview(std::string setOverview);
void SetTags(std::vector<std::string> tags);
void SetFile(std::string file);
void SetPath(std::string path);
@@ -145,6 +146,7 @@ class CVideoInfoTag : public IArchivable, public ISerializable, public ISortable
typedef std::vector< SActorInfo >::const_iterator iCast;
std::string m_strSet;
int m_iSetId;
std::string m_strSetOverview;
std::vector<std::string> m_tags;
std::string m_strFile;
std::string m_strPath;

0 comments on commit 8cf9ecd

Please sign in to comment.