aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjmarshallnz <jcmarsha@gmail.com>2012-02-27 12:35:20 -0800
committerjmarshallnz <jcmarsha@gmail.com>2012-02-27 12:35:20 -0800
commit44968ef49a52e595bc3aa1890ad09678c0e5762b (patch)
treeb0114d026c5c280c49a96d5ed1ff56b9ea47b029
parent772c95964aed6e953295e5ee056265a5585733ff (diff)
parent5981f29dd64503f4d31cf63847134b699b61e7db (diff)
Merge pull request #729 from jmarshallnz/smartplaylist_loopdiloop
smartplaylist infinite loop
-rw-r--r--xbmc/PartyModeManager.cpp6
-rw-r--r--xbmc/filesystem/SmartPlaylistDirectory.cpp13
-rw-r--r--xbmc/playlists/SmartPlayList.cpp50
-rw-r--r--xbmc/playlists/SmartPlayList.h12
4 files changed, 50 insertions, 31 deletions
diff --git a/xbmc/PartyModeManager.cpp b/xbmc/PartyModeManager.cpp
index 26b7290224..ecfaf78b98 100644
--- a/xbmc/PartyModeManager.cpp
+++ b/xbmc/PartyModeManager.cpp
@@ -111,8 +111,9 @@ bool CPartyModeManager::Enable(PartyModeContext context /*= PARTYMODECONTEXT_MUS
CMusicDatabase db;
if (db.Open())
{
+ set<CStdString> playlists;
if ( playlistLoaded )
- m_strCurrentFilterMusic = playlist.GetWhereClause(db);
+ m_strCurrentFilterMusic = playlist.GetWhereClause(db, playlists);
CLog::Log(LOGINFO, "PARTY MODE MANAGER: Registering filter:[%s]", m_strCurrentFilterMusic.c_str());
m_iMatchingSongs = (int)db.GetSongIDs(m_strCurrentFilterMusic, songIDs);
@@ -139,8 +140,9 @@ bool CPartyModeManager::Enable(PartyModeContext context /*= PARTYMODECONTEXT_MUS
CVideoDatabase db;
if (db.Open())
{
+ set<CStdString> playlists;
if ( playlistLoaded )
- m_strCurrentFilterVideo = playlist.GetWhereClause(db);
+ m_strCurrentFilterVideo = playlist.GetWhereClause(db, playlists);
CLog::Log(LOGINFO, "PARTY MODE MANAGER: Registering filter:[%s]", m_strCurrentFilterVideo.c_str());
m_iMatchingSongs += (int)db.GetMusicVideoIDs(m_strCurrentFilterVideo, songIDs2);
diff --git a/xbmc/filesystem/SmartPlaylistDirectory.cpp b/xbmc/filesystem/SmartPlaylistDirectory.cpp
index aa6668f888..45cf60756f 100644
--- a/xbmc/filesystem/SmartPlaylistDirectory.cpp
+++ b/xbmc/filesystem/SmartPlaylistDirectory.cpp
@@ -46,11 +46,12 @@ namespace XFILE
if (!playlist.Load(strPath))
return false;
bool success = false, success2 = false;
+ std::set<CStdString> playlists;
if (playlist.GetType().Equals("tvshows"))
{
CVideoDatabase db;
db.Open();
- CStdString whereOrder = playlist.GetWhereClause(db) + " " + playlist.GetOrderClause(db);
+ CStdString whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db);
success = db.GetTvShowsByWhere("videodb://2/2/", whereOrder, items);
items.SetContent("tvshows");
db.Close();
@@ -59,7 +60,7 @@ namespace XFILE
{
CVideoDatabase db;
db.Open();
- CStdString whereOrder = playlist.GetWhereClause(db) + " " + playlist.GetOrderClause(db);
+ CStdString whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db);
success = db.GetEpisodesByWhere("videodb://2/2/", whereOrder, items);
items.SetContent("episodes");
db.Close();
@@ -68,7 +69,7 @@ namespace XFILE
{
CVideoDatabase db;
db.Open();
- success = db.GetMoviesByWhere("videodb://1/2/", playlist.GetWhereClause(db), playlist.GetOrderClause(db), items, true);
+ success = db.GetMoviesByWhere("videodb://1/2/", playlist.GetWhereClause(db, playlists), playlist.GetOrderClause(db), items, true);
items.SetContent("movies");
db.Close();
}
@@ -76,7 +77,7 @@ namespace XFILE
{
CMusicDatabase db;
db.Open();
- success = db.GetAlbumsByWhere("musicdb://3/", playlist.GetWhereClause(db), playlist.GetOrderClause(db), items);
+ success = db.GetAlbumsByWhere("musicdb://3/", playlist.GetWhereClause(db, playlists), playlist.GetOrderClause(db), items);
items.SetContent("albums");
db.Close();
}
@@ -90,7 +91,7 @@ namespace XFILE
if (playlist.GetType().Equals("mixed"))
playlist.SetType("songs");
- CStdString whereOrder = playlist.GetWhereClause(db) + " " + playlist.GetOrderClause(db);
+ CStdString whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db);
success = db.GetSongsByWhere("", whereOrder, items);
items.SetContent("songs");
db.Close();
@@ -103,7 +104,7 @@ namespace XFILE
CStdString type=playlist.GetType();
if (playlist.GetType().Equals("mixed"))
playlist.SetType("musicvideos");
- CStdString whereOrder = playlist.GetWhereClause(db) + " " + playlist.GetOrderClause(db);
+ CStdString whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db);
CFileItemList items2;
success2 = db.GetMusicVideosByWhere("videodb://3/2/", whereOrder, items2, false); // TODO: SMARTPLAYLISTS Don't check locks???
db.Close();
diff --git a/xbmc/playlists/SmartPlayList.cpp b/xbmc/playlists/SmartPlayList.cpp
index f5d1ffa3a2..f99e519698 100644
--- a/xbmc/playlists/SmartPlayList.cpp
+++ b/xbmc/playlists/SmartPlayList.cpp
@@ -580,26 +580,6 @@ CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& s
query = "idFile" + negate + " in (select distinct idFile from streamdetails where strSubtitleLanguage " + parameter + ")";
else if (m_field == FIELD_VIDEOASPECT)
query = "idFile" + negate + " in (select distinct idFile from streamdetails where fVideoAspect " + parameter + ")";
- else if (m_field == FIELD_PLAYLIST)
- { // playlist field - grab our playlist and add to our where clause
- CStdString playlistFile = CSmartPlaylistDirectory::GetPlaylistByName(m_parameter, strType);
- if (!playlistFile.IsEmpty())
- {
- CSmartPlaylist playlist;
- playlist.Load(playlistFile);
- CStdString playlistQuery;
- // only playlists of same type will be part of the query
- if (playlist.GetType().Equals(strType) || (playlist.GetType().Equals("mixed") && (strType == "songs" || strType == "musicvideos")) || playlist.GetType().IsEmpty())
- {
- playlist.SetType(strType);
- playlistQuery = playlist.GetWhereClause(db, false);
- }
- if (m_operator == OPERATOR_DOES_NOT_EQUAL && playlist.GetType().Equals(strType))
- query.Format("NOT (%s)", playlistQuery.c_str());
- else if (m_operator == OPERATOR_EQUALS && playlist.GetType().Equals(strType))
- query = playlistQuery;
- }
- }
if (m_field == FIELD_PLAYCOUNT && strType != "songs" && strType != "albums")
{ // playcount is stored as NULL or number in video db
if ((m_operator == OPERATOR_EQUALS && m_parameter == "0") ||
@@ -931,7 +911,7 @@ void CSmartPlaylist::AddRule(const CSmartPlaylistRule &rule)
m_playlistRules.push_back(rule);
}
-CStdString CSmartPlaylist::GetWhereClause(CDatabase &db, bool needWhere /* = true */)
+CStdString CSmartPlaylist::GetWhereClause(CDatabase &db, set<CStdString> &referencedPlaylists, bool needWhere /* = true */)
{
CStdString rule, currentRule;
for (vector<CSmartPlaylistRule>::iterator it = m_playlistRules.begin(); it != m_playlistRules.end(); ++it)
@@ -941,7 +921,33 @@ CStdString CSmartPlaylist::GetWhereClause(CDatabase &db, bool needWhere /* = tru
else if (needWhere)
rule += "WHERE ";
rule += "(";
- currentRule = (*it).GetWhereClause(db, GetType());
+ CStdString currentRule;
+ if (it->m_field == CSmartPlaylistRule::FIELD_PLAYLIST)
+ {
+ CStdString playlistFile = CSmartPlaylistDirectory::GetPlaylistByName(it->m_parameter, GetType());
+ if (!playlistFile.IsEmpty() && referencedPlaylists.find(playlistFile) == referencedPlaylists.end())
+ {
+ referencedPlaylists.insert(playlistFile);
+ CSmartPlaylist playlist;
+ playlist.Load(playlistFile);
+ CStdString playlistQuery;
+ // only playlists of same type will be part of the query
+ if (playlist.GetType().Equals(GetType()) || (playlist.GetType().Equals("mixed") && (GetType() == "songs" || GetType() == "musicvideos")) || playlist.GetType().IsEmpty())
+ {
+ playlist.SetType(GetType());
+ playlistQuery = playlist.GetWhereClause(db, referencedPlaylists, false);
+ }
+ if (playlist.GetType().Equals(GetType()))
+ {
+ if (it->m_operator == CSmartPlaylistRule::OPERATOR_DOES_NOT_EQUAL)
+ currentRule.Format("NOT (%s)", playlistQuery.c_str());
+ else
+ currentRule = playlistQuery;
+ }
+ }
+ }
+ else
+ currentRule = (*it).GetWhereClause(db, GetType());
// if we don't get a rule, we add '1' or '0' so the query is still valid and doesn't fail
if (currentRule.IsEmpty())
currentRule = m_matchAllRules ? "'1'" : "'0'";
diff --git a/xbmc/playlists/SmartPlayList.h b/xbmc/playlists/SmartPlayList.h
index 5359a62aa5..4da982b642 100644
--- a/xbmc/playlists/SmartPlayList.h
+++ b/xbmc/playlists/SmartPlayList.h
@@ -23,6 +23,7 @@
#include "utils/StdString.h"
#include "tinyXML/tinyxml.h"
#include <vector>
+#include <set>
class CDatabase;
@@ -167,7 +168,16 @@ public:
bool GetOrderAscending() const { return m_orderAscending; };
void AddRule(const CSmartPlaylistRule &rule);
- CStdString GetWhereClause(CDatabase &db, bool needWhere = true);
+
+ /*! \brief get the where clause for a playlist
+ We handle playlists inside playlists separately in order to ensure we don't introduce infinite loops
+ by playlist A including playlist B which also (perhaps via other playlists) then includes playlistA.
+
+ \param db the database to use to format up results
+ \param referencedPlaylists a set of playlists to know when we reach a cycle
+ \param needWhere whether we need to prepend the where clause with "WHERE "
+ */
+ CStdString GetWhereClause(CDatabase &db, std::set<CStdString> &referencedPlaylists, bool needWhere = true);
CStdString GetOrderClause(CDatabase &db);
const std::vector<CSmartPlaylistRule> &GetRules() const;