PageRenderTime 31ms CodeModel.GetById 10ms app.highlight 18ms RepoModel.GetById 2ms app.codeStats 0ms

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