/xbmc/NfoFile.cpp

http://github.com/xbmc/xbmc · C++ · 190 lines · 147 code · 26 blank · 17 comment · 56 complexity · fdd7c88ee15f0bb7e60e8c61630d215d MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-2018 Team Kodi
  3. * This file is part of Kodi - https://kodi.tv
  4. *
  5. * SPDX-License-Identifier: GPL-2.0-or-later
  6. * See LICENSES/README.md for more information.
  7. */
  8. // NfoFile.cpp: implementation of the CNfoFile class.
  9. //
  10. //////////////////////////////////////////////////////////////////////
  11. #include "NfoFile.h"
  12. #include "FileItem.h"
  13. #include "ServiceBroker.h"
  14. #include "addons/AddonManager.h"
  15. #include "addons/AddonSystemSettings.h"
  16. #include "filesystem/File.h"
  17. #include "music/Album.h"
  18. #include "music/Artist.h"
  19. #include "video/VideoInfoDownloader.h"
  20. #include <string>
  21. #include <vector>
  22. using namespace XFILE;
  23. using namespace ADDON;
  24. CInfoScanner::INFO_TYPE CNfoFile::Create(const std::string& strPath,
  25. const ScraperPtr& info, int episode)
  26. {
  27. m_info = info; // assume we can use these settings
  28. m_type = ScraperTypeFromContent(info->Content());
  29. if (Load(strPath) != 0)
  30. return CInfoScanner::NO_NFO;
  31. CFileItemList items;
  32. bool bNfo=false;
  33. if (m_type == ADDON_SCRAPER_ALBUMS)
  34. {
  35. CAlbum album;
  36. bNfo = GetDetails(album);
  37. }
  38. else if (m_type == ADDON_SCRAPER_ARTISTS)
  39. {
  40. CArtist artist;
  41. bNfo = GetDetails(artist);
  42. }
  43. else if (m_type == ADDON_SCRAPER_TVSHOWS || m_type == ADDON_SCRAPER_MOVIES
  44. || m_type == ADDON_SCRAPER_MUSICVIDEOS)
  45. {
  46. // first check if it's an XML file with the info we need
  47. CVideoInfoTag details;
  48. bNfo = GetDetails(details);
  49. if (episode > -1 && bNfo && m_type == ADDON_SCRAPER_TVSHOWS)
  50. {
  51. int infos=0;
  52. while (m_headPos != std::string::npos && details.m_iEpisode != episode)
  53. {
  54. m_headPos = m_doc.find("<episodedetails", m_headPos + 1);
  55. if (m_headPos == std::string::npos)
  56. break;
  57. bNfo = GetDetails(details);
  58. infos++;
  59. }
  60. if (details.m_iEpisode != episode)
  61. {
  62. bNfo = false;
  63. details.Reset();
  64. m_headPos = 0;
  65. if (infos == 1) // still allow differing nfo/file numbers for single ep nfo's
  66. bNfo = GetDetails(details);
  67. }
  68. }
  69. }
  70. std::vector<ScraperPtr> vecScrapers = GetScrapers(m_type, m_info);
  71. // search ..
  72. int res = -1;
  73. for (unsigned int i=0; i<vecScrapers.size(); ++i)
  74. if ((res = Scrape(vecScrapers[i], m_scurl, m_doc)) == 0 || res == 2)
  75. break;
  76. if (res == 2)
  77. return CInfoScanner::ERROR_NFO;
  78. if (bNfo)
  79. {
  80. if (m_scurl.m_url.empty())
  81. {
  82. if (m_doc.find("[scrape url]") != std::string::npos)
  83. return CInfoScanner::OVERRIDE_NFO;
  84. else
  85. return CInfoScanner::FULL_NFO;
  86. }
  87. else
  88. return CInfoScanner::COMBINED_NFO;
  89. }
  90. return m_scurl.m_url.empty() ? CInfoScanner::NO_NFO : CInfoScanner::URL_NFO;
  91. }
  92. // return value: 0 - success; 1 - no result; skip; 2 - error
  93. int CNfoFile::Scrape(ScraperPtr& scraper, CScraperUrl& url,
  94. const std::string& content)
  95. {
  96. if (scraper->IsNoop())
  97. {
  98. url = CScraperUrl();
  99. return 0;
  100. }
  101. scraper->ClearCache();
  102. try
  103. {
  104. url = scraper->NfoUrl(content);
  105. }
  106. catch (const CScraperError &sce)
  107. {
  108. CVideoInfoDownloader::ShowErrorDialog(sce);
  109. if (!sce.FAborted())
  110. return 2;
  111. }
  112. return url.m_url.empty() ? 1 : 0;
  113. }
  114. int CNfoFile::Load(const std::string& strFile)
  115. {
  116. Close();
  117. XFILE::CFile file;
  118. XFILE::auto_buffer buf;
  119. if (file.LoadFile(strFile, buf) > 0)
  120. {
  121. m_doc.assign(buf.get(), buf.size());
  122. m_headPos = 0;
  123. return 0;
  124. }
  125. m_doc.clear();
  126. return 1;
  127. }
  128. void CNfoFile::Close()
  129. {
  130. m_doc.clear();
  131. m_headPos = 0;
  132. m_scurl.Clear();
  133. }
  134. std::vector<ScraperPtr> CNfoFile::GetScrapers(TYPE type,
  135. ScraperPtr selectedScraper)
  136. {
  137. AddonPtr addon;
  138. ScraperPtr defaultScraper;
  139. if (CAddonSystemSettings::GetInstance().GetActive(type, addon))
  140. defaultScraper = std::dynamic_pointer_cast<CScraper>(addon);
  141. std::vector<ScraperPtr> vecScrapers;
  142. // add selected scraper - first priority
  143. if (selectedScraper)
  144. vecScrapers.push_back(selectedScraper);
  145. // Add all scrapers except selected and default
  146. VECADDONS addons;
  147. CServiceBroker::GetAddonMgr().GetAddons(addons, type);
  148. for (auto& addon : addons)
  149. {
  150. ScraperPtr scraper = std::dynamic_pointer_cast<CScraper>(addon);
  151. // skip if scraper requires settings and there's nothing set yet
  152. if (scraper->RequiresSettings() && !scraper->HasUserSettings())
  153. continue;
  154. if ((!selectedScraper || selectedScraper->ID() != scraper->ID()) &&
  155. (!defaultScraper || defaultScraper->ID() != scraper->ID()))
  156. vecScrapers.push_back(scraper);
  157. }
  158. // add default scraper - not user selectable so it's last priority
  159. if (defaultScraper && (!selectedScraper ||
  160. selectedScraper->ID() != defaultScraper->ID()) &&
  161. (!defaultScraper->RequiresSettings() || defaultScraper->HasUserSettings()))
  162. vecScrapers.push_back(defaultScraper);
  163. return vecScrapers;
  164. }