diff options
Diffstat (limited to 'xbmc/playlists/PlayListXSPF.cpp')
-rw-r--r-- | xbmc/playlists/PlayListXSPF.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/xbmc/playlists/PlayListXSPF.cpp b/xbmc/playlists/PlayListXSPF.cpp new file mode 100644 index 0000000..6f665a7 --- /dev/null +++ b/xbmc/playlists/PlayListXSPF.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2018 Tyler Szabo + * Copyright (C) 2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "PlayListXSPF.h" + +#include "FileItem.h" +#include "URL.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "utils/XBMCTinyXML.h" +#include "utils/log.h" + +using namespace PLAYLIST; + +namespace +{ + +constexpr char const* LOCATION_TAGNAME = "location"; +constexpr char const* PLAYLIST_TAGNAME = "playlist"; +constexpr char const* TITLE_TAGNAME = "title"; +constexpr char const* TRACK_TAGNAME = "track"; +constexpr char const* TRACKLIST_TAGNAME = "trackList"; + +std::string GetXMLText(const TiXmlElement* pXmlElement) +{ + std::string result; + if (pXmlElement) + { + const char* const innerText = pXmlElement->GetText(); + if (innerText) + result = innerText; + } + return result; +} + +} + +CPlayListXSPF::CPlayListXSPF(void) = default; + +CPlayListXSPF::~CPlayListXSPF(void) = default; + +bool CPlayListXSPF::Load(const std::string& strFileName) +{ + CXBMCTinyXML xmlDoc; + + if (!xmlDoc.LoadFile(strFileName)) + { + CLog::Log(LOGERROR, "Error parsing XML file {} ({}, {}): {}", strFileName, xmlDoc.ErrorRow(), + xmlDoc.ErrorCol(), xmlDoc.ErrorDesc()); + return false; + } + + TiXmlElement* pPlaylist = xmlDoc.FirstChildElement(PLAYLIST_TAGNAME); + if (!pPlaylist) + { + CLog::Log(LOGERROR, "Error parsing XML file {}: missing root element {}", strFileName, + PLAYLIST_TAGNAME); + return false; + } + + TiXmlElement* pTracklist = pPlaylist->FirstChildElement(TRACKLIST_TAGNAME); + if (!pTracklist) + { + CLog::Log(LOGERROR, "Error parsing XML file {}: missing element {}", strFileName, + TRACKLIST_TAGNAME); + return false; + } + + Clear(); + URIUtils::GetParentPath(strFileName, m_strBasePath); + + m_strPlayListName = GetXMLText(pPlaylist->FirstChildElement(TITLE_TAGNAME)); + + TiXmlElement* pCurTrack = pTracklist->FirstChildElement(TRACK_TAGNAME); + while (pCurTrack) + { + std::string location = GetXMLText(pCurTrack->FirstChildElement(LOCATION_TAGNAME)); + if (!location.empty()) + { + std::string label = GetXMLText(pCurTrack->FirstChildElement(TITLE_TAGNAME)); + + CFileItemPtr newItem(new CFileItem(label)); + + CURL uri(location); + + // at the time of writing CURL doesn't handle file:// URI scheme the way + // it's presented in this format, parse to local path instead + std::string localpath; + if (StringUtils::StartsWith(location, "file:///")) + { +#ifndef TARGET_WINDOWS + // Linux absolute path must start with root + localpath = "/"; +#endif + // Path starts after "file:///" + localpath += CURL::Decode(location.substr(8)); + } + else if (uri.GetProtocol().empty()) + { + localpath = URIUtils::AppendSlash(m_strBasePath) + CURL::Decode(location); + } + + if (!localpath.empty()) + { + // We don't use URIUtils::CanonicalizePath because m_strBasePath may be a + // protocol e.g. smb +#ifdef TARGET_WINDOWS + StringUtils::Replace(localpath, "/", "\\"); +#endif + localpath = URIUtils::GetRealPath(localpath); + + newItem->SetPath(localpath); + } + else + { + newItem->SetURL(uri); + } + + Add(newItem); + } + + pCurTrack = pCurTrack->NextSiblingElement(TRACK_TAGNAME); + } + + return true; +} |