Skip to content

Commit

Permalink
smartplaylists: refactor XML reading/writing
Browse files Browse the repository at this point in the history
  • Loading branch information
Montellese committed Feb 2, 2013
1 parent 009fce9 commit 7c72901
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 72 deletions.
142 changes: 78 additions & 64 deletions xbmc/playlists/SmartPlayList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,12 @@ CSmartPlaylistRule::CSmartPlaylistRule()
m_parameter.clear();
}

bool CSmartPlaylistRule::Load(TiXmlElement *element, const CStdString &encoding /* = "UTF-8" */)
bool CSmartPlaylistRule::Load(const TiXmlNode *node, const std::string &encoding /* = "UTF-8" */)
{
if (node == NULL)
return false;

const TiXmlElement *element = node->ToElement();
if (element == NULL)
return false;

Expand All @@ -165,14 +169,14 @@ bool CSmartPlaylistRule::Load(TiXmlElement *element, const CStdString &encoding
if (m_operator == OPERATOR_TRUE || m_operator == OPERATOR_FALSE)
return true;

TiXmlNode *parameter = element->FirstChild();
const TiXmlNode *parameter = element->FirstChild();
if (parameter == NULL)
return false;

if (parameter->Type() == TiXmlNode::TINYXML_TEXT)
{
CStdString utf8Parameter;
if (encoding.IsEmpty()) // utf8
if (encoding.empty()) // utf8
utf8Parameter = parameter->ValueStr();
else
g_charsetConverter.stringCharsetToUtf8(encoding, parameter->ValueStr(), utf8Parameter);
Expand All @@ -182,14 +186,14 @@ bool CSmartPlaylistRule::Load(TiXmlElement *element, const CStdString &encoding
}
else if (parameter->Type() == TiXmlNode::TINYXML_ELEMENT)
{
TiXmlElement *valueElem = element->FirstChildElement("value");
while (valueElem != NULL)
const TiXmlNode *valueNode = element->FirstChild("value");
while (valueNode != NULL)
{
TiXmlNode *value = valueElem->FirstChild();
const TiXmlNode *value = valueNode->FirstChild();
if (value != NULL && value->Type() == TiXmlNode::TINYXML_TEXT)
{
CStdString utf8Parameter;
if (encoding.IsEmpty()) // utf8
if (encoding.empty()) // utf8
utf8Parameter = value->ValueStr();
else
g_charsetConverter.stringCharsetToUtf8(encoding, value->ValueStr(), utf8Parameter);
Expand All @@ -198,7 +202,7 @@ bool CSmartPlaylistRule::Load(TiXmlElement *element, const CStdString &encoding
m_parameter.push_back(utf8Parameter);
}

valueElem = valueElem->NextSiblingElement("value");
valueNode = valueNode->NextSibling("value");
}
}
else
Expand Down Expand Up @@ -1136,44 +1140,31 @@ CSmartPlaylist::CSmartPlaylist()
Reset();
}

TiXmlElement *CSmartPlaylist::OpenAndReadName(const CStdString &path)
bool CSmartPlaylist::OpenAndReadName(const CStdString &path)
{
CFileStream file;
if (!file.Open(path))
{
CLog::Log(LOGERROR, "Error loading Smart playlist %s (failed to read file)", path.c_str());
return NULL;
}

m_xmlDoc.Clear();
file >> m_xmlDoc;
if (readNameFromPath(path) == NULL)
return false;

TiXmlElement *root = readName();
if (m_playlistName.empty())
{
m_playlistName = CUtil::GetTitleFromPath(path);
if (URIUtils::GetExtension(m_playlistName) == ".xsp")
URIUtils::RemoveExtension(m_playlistName);
}
return root;
return !m_playlistName.empty();
}

TiXmlElement* CSmartPlaylist::readName()
const TiXmlNode* CSmartPlaylist::readName(const TiXmlNode *root)
{
if (m_xmlDoc.Error())
{
CLog::Log(LOGERROR, "Error loading Smart playlist (failed to parse xml: %s)", m_xmlDoc.ErrorDesc());
if (root == NULL)
return NULL;

const TiXmlElement *rootElem = root->ToElement();
if (rootElem == NULL)
return NULL;
}

TiXmlElement *root = m_xmlDoc.RootElement();
if (!root || !StringUtils::EqualsNoCase(root->Value(),"smartplaylist"))
{
CLog::Log(LOGERROR, "Error loading Smart playlist");
return NULL;
}

// load the playlist type
const char* type = root->Attribute("type");
const char* type = rootElem->Attribute("type");
if (type)
m_playlistType = type;
// backward compatibility:
Expand All @@ -1183,14 +1174,37 @@ TiXmlElement* CSmartPlaylist::readName()
m_playlistType = "musicvideos";

// load the playlist name
TiXmlHandle name = ((TiXmlHandle)root->FirstChild("name")).FirstChild();
if (name.Node())
m_playlistName = name.Node()->Value();
const TiXmlNode *name = rootElem->FirstChild("name");
if (name != NULL && name->FirstChild() != NULL)
m_playlistName = name->FirstChild()->Value();

return root;
}

TiXmlElement *CSmartPlaylist::readNameFromXml(const CStdString &xml)
const TiXmlNode* CSmartPlaylist::readNameFromPath(const CStdString &path)
{
CFileStream file;
if (!file.Open(path))
{
CLog::Log(LOGERROR, "Error loading Smart playlist %s (failed to read file)", path.c_str());
return NULL;
}

m_xmlDoc.Clear();
file >> m_xmlDoc;

const TiXmlNode *root = readName(m_xmlDoc.RootElement());
if (m_playlistName.empty())
{
m_playlistName = CUtil::GetTitleFromPath(path);
if (URIUtils::GetExtension(m_playlistName) == ".xsp")
URIUtils::RemoveExtension(m_playlistName);
}

return root;
}

const TiXmlNode* CSmartPlaylist::readNameFromXml(const CStdString &xml)
{
if (xml.empty())
{
Expand All @@ -1205,12 +1219,25 @@ TiXmlElement *CSmartPlaylist::readNameFromXml(const CStdString &xml)
return NULL;
}

return readName();
const TiXmlNode *root = readName(m_xmlDoc.RootElement());

return root;
}

bool CSmartPlaylist::load(const TiXmlNode *root)
{
if (root == NULL)
return false;

CStdString encoding;
XMLUtils::GetEncoding(&m_xmlDoc, encoding);

return LoadFromXML(root, encoding);
}

bool CSmartPlaylist::Load(const CStdString &path)
{
return load(OpenAndReadName(path));
return load(readNameFromPath(path));
}

bool CSmartPlaylist::Load(const CVariant &obj)
Expand Down Expand Up @@ -1256,48 +1283,35 @@ bool CSmartPlaylist::LoadFromXml(const CStdString &xml)
return load(readNameFromXml(xml));
}

bool CSmartPlaylist::load(TiXmlElement *root)
{
if (!root)
return false;

// encoding:
CStdString encoding;
XMLUtils::GetEncoding(&m_xmlDoc, encoding);

// from here we decode from XML
return LoadFromXML(root, encoding);
}

bool CSmartPlaylist::LoadFromXML(TiXmlElement *root, const CStdString &encoding)
bool CSmartPlaylist::LoadFromXML(const TiXmlNode *root, const CStdString &encoding)
{
if (!root)
return false;

TiXmlHandle match = ((TiXmlHandle)root->FirstChild("match")).FirstChild();
if (match.Node())
m_ruleCombination.SetType(StringUtils::EqualsNoCase(match.Node()->ValueStr(), "all") ? CSmartPlaylistRuleCombination::CombinationAnd : CSmartPlaylistRuleCombination::CombinationOr);
const TiXmlNode *match = root->FirstChild("match");
if (match != NULL && match->FirstChild() != NULL)
m_ruleCombination.SetType(StringUtils::EqualsNoCase(match->FirstChild()->ValueStr(), "all") ? CSmartPlaylistRuleCombination::CombinationAnd : CSmartPlaylistRuleCombination::CombinationOr);

// now the rules
TiXmlElement *ruleElement = root->FirstChildElement("rule");
while (ruleElement)
const TiXmlNode *ruleNode = root->FirstChild("rule");
while (ruleNode)
{
CSmartPlaylistRule rule;
if (rule.Load(ruleElement, encoding))
if (rule.Load(ruleNode, encoding))
m_ruleCombination.AddRule(rule);

ruleElement = ruleElement->NextSiblingElement("rule");
ruleNode = ruleNode->NextSibling("rule");
}

// now any limits
// format is <limit>25</limit>
TiXmlHandle limit = ((TiXmlHandle)root->FirstChild("limit")).FirstChild();
if (limit.Node())
m_limit = atoi(limit.Node()->Value());
const TiXmlNode *limit = root->FirstChild("limit");
if (limit != NULL && limit->FirstChild() != NULL)
m_limit = strtol(limit->FirstChild()->Value(), NULL, 0);

// and order
// format is <order direction="ascending">field</order>
TiXmlElement *order = root->FirstChildElement("order");
const TiXmlElement *order = root->FirstChildElement("order");
if (order && order->FirstChild())
{
const char *direction = order->Attribute("direction");
Expand Down
20 changes: 12 additions & 8 deletions xbmc/playlists/SmartPlayList.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class ISmartPlaylistRule
public:
virtual ~ISmartPlaylistRule() { }

virtual bool Load(TiXmlElement *element, const CStdString &encoding = "UTF-8") = 0;
virtual bool Load(const TiXmlNode *node, const std::string &encoding = "UTF-8") = 0;
virtual bool Load(const CVariant &obj) = 0;
virtual bool Save(TiXmlNode *parent) const = 0;
virtual bool Save(CVariant &obj) const = 0;
Expand All @@ -44,6 +44,7 @@ class CSmartPlaylistRule : public ISmartPlaylistRule
{
public:
CSmartPlaylistRule();
virtual ~CSmartPlaylistRule() { }

enum SEARCH_OPERATOR { OPERATOR_START = 0,
OPERATOR_CONTAINS,
Expand Down Expand Up @@ -75,7 +76,7 @@ class CSmartPlaylistRule : public ISmartPlaylistRule
TEXTIN_FIELD
};

virtual bool Load(TiXmlElement *element, const CStdString &encoding = "UTF-8");
virtual bool Load(const TiXmlNode *node, const std::string &encoding = "UTF-8");
virtual bool Load(const CVariant &obj);
virtual bool Save(TiXmlNode *parent) const;
virtual bool Save(CVariant &obj) const;
Expand Down Expand Up @@ -117,13 +118,14 @@ class CSmartPlaylistRuleCombination : public ISmartPlaylistRule
{
public:
CSmartPlaylistRuleCombination();
virtual ~CSmartPlaylistRuleCombination() { }

typedef enum {
CombinationOr = 0,
CombinationAnd
} Combination;

virtual bool Load(TiXmlElement *element, const CStdString &encoding = "UTF-8") { return false; }
virtual bool Load(const TiXmlNode *node, const std::string &encoding = "UTF-8") { return false; }
virtual bool Load(const CVariant &obj);
virtual bool Save(TiXmlNode *parent) const { return false; }
virtual bool Save(CVariant &obj) const;
Expand Down Expand Up @@ -151,6 +153,7 @@ class CSmartPlaylist
{
public:
CSmartPlaylist();
virtual ~CSmartPlaylist() { }

bool Load(const CStdString &path);
bool Load(const CVariant &obj);
Expand All @@ -160,8 +163,8 @@ class CSmartPlaylist
bool Save(CVariant &obj, bool full = true) const;
bool SaveAsJson(CStdString &json, bool full = true) const;

TiXmlElement *OpenAndReadName(const CStdString &path);
bool LoadFromXML(TiXmlElement *root, const CStdString &encoding = "UTF-8");
bool OpenAndReadName(const CStdString &path);
bool LoadFromXML(const TiXmlNode *root, const CStdString &encoding = "UTF-8");

void Reset();

Expand Down Expand Up @@ -203,9 +206,10 @@ class CSmartPlaylist
friend class CGUIDialogSmartPlaylistEditor;
friend class CGUIDialogMediaFilter;

TiXmlElement* readName();
TiXmlElement *readNameFromXml(const CStdString &xml);
bool load(TiXmlElement *root);
const TiXmlNode* readName(const TiXmlNode *root);
const TiXmlNode* readNameFromPath(const CStdString &path);
const TiXmlNode* readNameFromXml(const CStdString &xml);
bool load(const TiXmlNode *root);

CSmartPlaylistRuleCombination m_ruleCombination;
CStdString m_playlistName;
Expand Down

0 comments on commit 7c72901

Please sign in to comment.