[cosmetics] update date in GPL header
[vuplus_xbmc] / xbmc / video / VideoInfoDownloader.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
21 #include "VideoInfoDownloader.h"
22 #include "utils/XMLUtils.h"
23 #include "utils/RegExp.h"
24 #include "NfoFile.h"
25 #include "dialogs/GUIDialogProgress.h"
26 #include "dialogs/GUIDialogOK.h"
27 #include "ApplicationMessenger.h"
28 #include "guilib/GUIWindowManager.h"
29 #include "guilib/LocalizeStrings.h"
30 #include "utils/log.h"
31 #include "utils/URIUtils.h"
32
33 using namespace std;
34 using namespace VIDEO;
35
36 #ifndef __GNUC__
37 #pragma warning (disable:4018)
38 #endif
39
40 CVideoInfoDownloader::CVideoInfoDownloader(const ADDON::ScraperPtr &scraper) :
41   CThread("CVideoInfoDownloader"), m_state(DO_NOTHING), m_found(0), m_info(scraper)
42 {
43   m_http = new XFILE::CCurlFile;
44 }
45
46 CVideoInfoDownloader::~CVideoInfoDownloader()
47 {
48   delete m_http;
49 }
50
51 // return value: 0 = we failed, -1 = we failed and reported an error, 1 = success
52 int CVideoInfoDownloader::InternalFindMovie(const CStdString &strMovie,
53                                             MOVIELIST& movielist,
54                                             bool cleanChars /* = true */)
55 {
56   try
57   {
58     movielist = m_info->FindMovie(*m_http, strMovie, cleanChars);
59   }
60   catch (const ADDON::CScraperError &sce)
61   {
62     ShowErrorDialog(sce);
63     return sce.FAborted() ? 0 : -1;
64   }
65   return 1;  // success
66 }
67
68 void CVideoInfoDownloader::ShowErrorDialog(const ADDON::CScraperError &sce)
69 {
70   if (!sce.Title().empty())
71   {
72     CGUIDialogOK *pdlg = (CGUIDialogOK *)g_windowManager.GetWindow(WINDOW_DIALOG_OK);
73     pdlg->SetHeading(sce.Title());
74     pdlg->SetLine(0, sce.Message());
75     CApplicationMessenger::Get().DoModal(pdlg, WINDOW_DIALOG_OK);
76   }
77 }
78
79 // threaded functions
80 void CVideoInfoDownloader::Process()
81 {
82   // note here that we're calling our external functions but we're calling them with
83   // no progress bar set, so they're effectively calling our internal functions directly.
84   m_found = 0;
85   if (m_state == FIND_MOVIE)
86   {
87     if (!(m_found=FindMovie(m_strMovie, m_movieList)))
88       CLog::Log(LOGERROR, "%s: Error looking up item %s", __FUNCTION__, m_strMovie.c_str());
89     m_state = DO_NOTHING;
90     return;
91   }
92
93   if (m_url.m_url.empty())
94   {
95     // empty url when it's not supposed to be..
96     // this might happen if the previously scraped item was removed from the site (see ticket #10537)
97     CLog::Log(LOGERROR, "%s: Error getting details for %s due to an empty url", __FUNCTION__, m_strMovie.c_str());
98   }
99   else if (m_state == GET_DETAILS)
100   {
101     if (!GetDetails(m_url, m_movieDetails))
102       CLog::Log(LOGERROR, "%s: Error getting details from %s", __FUNCTION__,m_url.m_url[0].m_url.c_str());
103   }
104   else if (m_state == GET_EPISODE_DETAILS)
105   {
106     if (!GetEpisodeDetails(m_url, m_movieDetails))
107       CLog::Log(LOGERROR, "%s: Error getting episode details from %s", __FUNCTION__, m_url.m_url[0].m_url.c_str());
108   }
109   else if (m_state == GET_EPISODE_LIST)
110   {
111     if (!GetEpisodeList(m_url, m_episode))
112       CLog::Log(LOGERROR, "%s: Error getting episode list from %s", __FUNCTION__, m_url.m_url[0].m_url.c_str());
113   }
114   m_found = 1;
115   m_state = DO_NOTHING;
116 }
117
118 int CVideoInfoDownloader::FindMovie(const CStdString &strMovie,
119                                     MOVIELIST& movieList,
120                                     CGUIDialogProgress *pProgress /* = NULL */)
121 {
122   //CLog::Log(LOGDEBUG,"CVideoInfoDownloader::FindMovie(%s)", strMovie.c_str());
123
124   if (pProgress)
125   { // threaded version
126     m_state = FIND_MOVIE;
127     m_strMovie = strMovie;
128     m_found = 0;
129     if (IsRunning())
130       StopThread();
131     Create();
132     while (m_state != DO_NOTHING)
133     {
134       pProgress->Progress();
135       if (pProgress->IsCanceled())
136       {
137         CloseThread();
138         return 0;
139       }
140       Sleep(1);
141     }
142     // transfer to our movielist
143     m_movieList.swap(movieList);
144     int found=m_found;
145     CloseThread();
146     return found;
147   }
148
149   // unthreaded
150   int success = InternalFindMovie(strMovie, movieList);
151   // NOTE: this might be improved by rescraping if the match quality isn't high?
152   if (success == 1 && movieList.empty())
153   { // no results. try without cleaning chars like '.' and '_'
154     success = InternalFindMovie(strMovie, movieList, false);
155   }
156   return success;
157 }
158
159 bool CVideoInfoDownloader::GetDetails(const CScraperUrl &url,
160                                       CVideoInfoTag &movieDetails,
161                                       CGUIDialogProgress *pProgress /* = NULL */)
162 {
163   //CLog::Log(LOGDEBUG,"CVideoInfoDownloader::GetDetails(%s)", url.m_strURL.c_str());
164   m_url = url;
165   m_movieDetails = movieDetails;
166
167   // fill in the defaults
168   movieDetails.Reset();
169   if (pProgress)
170   { // threaded version
171     m_state = GET_DETAILS;
172     m_found = 0;
173     if (IsRunning())
174       StopThread();
175     Create();
176     while (!m_found)
177     {
178       pProgress->Progress();
179       if (pProgress->IsCanceled())
180       {
181         CloseThread();
182         return false;
183       }
184       Sleep(1);
185     }
186     movieDetails = m_movieDetails;
187     CloseThread();
188     return true;
189   }
190   else  // unthreaded
191     return m_info->GetVideoDetails(*m_http, url, true/*fMovie*/, movieDetails);
192 }
193
194 bool CVideoInfoDownloader::GetEpisodeDetails(const CScraperUrl &url,
195                                              CVideoInfoTag &movieDetails,
196                                              CGUIDialogProgress *pProgress /* = NULL */)
197 {
198   //CLog::Log(LOGDEBUG,"CVideoInfoDownloader::GetDetails(%s)", url.m_strURL.c_str());
199   m_url = url;
200   m_movieDetails = movieDetails;
201
202   // fill in the defaults
203   movieDetails.Reset();
204   if (pProgress)
205   { // threaded version
206     m_state = GET_EPISODE_DETAILS;
207     m_found = 0;
208     if (IsRunning())
209       StopThread();
210     Create();
211     while (!m_found)
212     {
213       pProgress->Progress();
214       if (pProgress->IsCanceled())
215       {
216         CloseThread();
217         return false;
218       }
219       Sleep(1);
220     }
221     movieDetails = m_movieDetails;
222     CloseThread();
223     return true;
224   }
225   else  // unthreaded
226     return m_info->GetVideoDetails(*m_http, url, false/*fMovie*/, movieDetails);
227 }
228
229 bool CVideoInfoDownloader::GetEpisodeList(const CScraperUrl& url,
230                                           EPISODELIST& movieDetails,
231                                           CGUIDialogProgress *pProgress /* = NULL */)
232 {
233   //CLog::Log(LOGDEBUG,"CVideoInfoDownloader::GetDetails(%s)", url.m_strURL.c_str());
234   m_url = url;
235   m_episode = movieDetails;
236
237   // fill in the defaults
238   movieDetails.clear();
239   if (pProgress)
240   { // threaded version
241     m_state = GET_EPISODE_LIST;
242     m_found = 0;
243     if (IsRunning())
244       StopThread();
245     Create();
246     while (!m_found)
247     {
248       pProgress->Progress();
249       if (pProgress->IsCanceled())
250       {
251         CloseThread();
252         return false;
253       }
254       Sleep(1);
255     }
256     movieDetails = m_episode;
257     CloseThread();
258     return true;
259   }
260   else  // unthreaded
261     return !(movieDetails = m_info->GetEpisodeList(*m_http, url)).empty();
262 }
263
264 void CVideoInfoDownloader::CloseThread()
265 {
266   m_http->Cancel();
267   StopThread();
268   m_http->Reset();
269   m_state = DO_NOTHING;
270   m_found = 0;
271 }
272