Merge pull request #2660 from Montellese/settings_refactor
[vuplus_xbmc] / xbmc / NfoFile.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20 // NfoFile.cpp: implementation of the CNfoFile class.
21 //
22 //////////////////////////////////////////////////////////////////////
23
24 #include "NfoFile.h"
25 #include "video/VideoInfoDownloader.h"
26 #include "addons/AddonManager.h"
27 #include "filesystem/File.h"
28 #include "FileItem.h"
29 #include "music/Album.h"
30 #include "music/Artist.h"
31 #include "settings/Settings.h"
32 #include "utils/log.h"
33
34 #include <vector>
35
36 using namespace std;
37 using namespace XFILE;
38 using namespace ADDON;
39
40 CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, const ScraperPtr& info, int episode, const CStdString& strPath2)
41 {
42   m_info = info; // assume we can use these settings
43   m_type = ScraperTypeFromContent(info->Content());
44   if (FAILED(Load(strPath)))
45     return NO_NFO;
46
47   CFileItemList items;
48   bool bNfo=false;
49
50   AddonPtr addon;
51   ScraperPtr defaultScraper;
52   if (CAddonMgr::Get().GetDefault(m_type, addon))
53     defaultScraper = boost::dynamic_pointer_cast<CScraper>(addon);
54
55   if (m_type == ADDON_SCRAPER_ALBUMS)
56   {
57     CAlbum album;
58     bNfo = GetDetails(album);
59   }
60   else if (m_type == ADDON_SCRAPER_ARTISTS)
61   {
62     CArtist artist;
63     bNfo = GetDetails(artist);
64   }
65   else if (m_type == ADDON_SCRAPER_TVSHOWS || m_type == ADDON_SCRAPER_MOVIES || m_type == ADDON_SCRAPER_MUSICVIDEOS)
66   {
67     // first check if it's an XML file with the info we need
68     CVideoInfoTag details;
69     bNfo = GetDetails(details);
70     if (episode > -1 && bNfo && m_type == ADDON_SCRAPER_TVSHOWS)
71     {
72       int infos=0;
73       m_headofdoc = strstr(m_headofdoc,"<episodedetails");
74       while (m_headofdoc && details.m_iEpisode != episode)
75       {
76         m_headofdoc = strstr(m_headofdoc+1,"<episodedetails");
77         bNfo  = GetDetails(details);
78         infos++;
79       }
80       if (details.m_iEpisode != episode)
81       {
82         bNfo = false;
83         details.Reset();
84         m_headofdoc = m_doc;
85         if (infos == 1) // still allow differing nfo/file numbers for single ep nfo's
86           bNfo = GetDetails(details);
87       }
88     }
89   }
90
91   vector<ScraperPtr> vecScrapers;
92
93   // add selected scraper - first proirity
94   if (m_info)
95     vecScrapers.push_back(m_info);
96
97   // Add all scrapers except selected and default
98   VECADDONS addons;
99   CAddonMgr::Get().GetAddons(m_type,addons);
100
101   for (unsigned i = 0; i < addons.size(); ++i)
102   {
103     ScraperPtr scraper = boost::dynamic_pointer_cast<CScraper>(addons[i]);
104
105     // skip if scraper requires settings and there's nothing set yet
106     if (scraper->RequiresSettings() && !scraper->HasUserSettings())
107       continue;
108
109     if( (!m_info || m_info->ID() != scraper->ID()) && (!defaultScraper || defaultScraper->ID() != scraper->ID()) )
110       vecScrapers.push_back(scraper);
111   }
112
113   // add default scraper - not user selectable so it's last priority
114   if( defaultScraper && (!m_info || m_info->ID() != defaultScraper->ID()) &&
115       ( !defaultScraper->RequiresSettings() || defaultScraper->HasUserSettings() ) )
116     vecScrapers.push_back(defaultScraper);
117
118   // search ..
119   int res = -1;
120   for (unsigned int i=0;i<vecScrapers.size();++i)
121     if ((res = Scrape(vecScrapers[i])) == 0 || res == 2)
122       break;
123
124   if (res == 2)
125     return ERROR_NFO;
126   if (bNfo)
127     return m_scurl.m_url.empty() ? FULL_NFO : COMBINED_NFO;
128   return m_scurl.m_url.empty() ? NO_NFO : URL_NFO;
129 }
130
131 // return value: 0 - success; 1 - no result; skip; 2 - error
132 int CNfoFile::Scrape(ScraperPtr& scraper)
133 {
134   if (scraper->IsNoop())
135   {
136     m_scurl = CScraperUrl();
137     return 0;
138   }
139   if (scraper->Type() != m_type)
140     return 1;
141   scraper->ClearCache();
142
143   try
144   {
145     m_scurl = scraper->NfoUrl(m_doc);
146   }
147   catch (const CScraperError &sce)
148   {
149     CVideoInfoDownloader::ShowErrorDialog(sce);
150     if (!sce.FAborted())
151       return 2;
152   }
153
154   if (!m_scurl.m_url.empty())
155     SetScraperInfo(scraper);
156   return m_scurl.m_url.empty() ? 1 : 0;
157 }
158
159 int CNfoFile::Load(const CStdString& strFile)
160 {
161   Close();
162   XFILE::CFile file;
163   if (file.Open(strFile))
164   {
165     int size = (int)file.GetLength();
166     try
167     {
168       m_doc = new char[size+1];
169       m_headofdoc = m_doc;
170     }
171     catch (...)
172     {
173       CLog::Log(LOGERROR, "%s: Exception while creating file buffer",__FUNCTION__);
174       return 1;
175     }
176     if (!m_doc)
177     {
178       file.Close();
179       return 1;
180     }
181     file.Read(m_doc, size);
182     m_doc[size] = 0;
183     file.Close();
184     return 0;
185   }
186   return 1;
187 }
188
189 void CNfoFile::Close()
190 {
191   delete[] m_doc;
192   m_doc = NULL;
193   m_scurl.Clear();
194 }