Merge pull request #26373 from ksooo/app-fix-multi-resolve-playback
[xbmc.git] / xbmc / video / VideoInfoDownloader.cpp
blob076b7ed80df9b7e35145de473b98e76c6606fda9
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "VideoInfoDownloader.h"
11 #include "dialogs/GUIDialogProgress.h"
12 #include "filesystem/CurlFile.h"
13 #include "messaging/helpers/DialogOKHelper.h"
14 #include "utils/Variant.h"
15 #include "utils/log.h"
17 using namespace KODI;
18 using namespace KODI::MESSAGING;
19 using namespace std::chrono_literals;
21 #ifndef __GNUC__
22 #pragma warning (disable:4018)
23 #endif
25 CVideoInfoDownloader::CVideoInfoDownloader(const ADDON::ScraperPtr& scraper)
26 : CThread("VideoInfoDownloader"), m_info(scraper)
28 m_http = new XFILE::CCurlFile;
31 CVideoInfoDownloader::~CVideoInfoDownloader()
33 delete m_http;
36 // return value: 0 = we failed, -1 = we failed and reported an error, 1 = success
37 int CVideoInfoDownloader::InternalFindMovie(const std::string &movieTitle, int movieYear,
38 MOVIELIST& movielist,
39 bool cleanChars /* = true */)
41 try
43 movielist = m_info->FindMovie(*m_http, movieTitle, movieYear, cleanChars);
45 catch (const ADDON::CScraperError &sce)
47 ShowErrorDialog(sce);
48 return sce.FAborted() ? 0 : -1;
50 return 1; // success
53 void CVideoInfoDownloader::ShowErrorDialog(const ADDON::CScraperError &sce)
55 if (!sce.Title().empty())
56 HELPERS::ShowOKDialogText(CVariant{ sce.Title() }, CVariant{ sce.Message() });
59 // threaded functions
60 void CVideoInfoDownloader::Process()
62 // note here that we're calling our external functions but we're calling them with
63 // no progress bar set, so they're effectively calling our internal functions directly.
64 m_found = 0;
65 if (m_state == FIND_MOVIE)
67 if (!(m_found=FindMovie(m_movieTitle, m_movieYear, m_movieList)))
68 CLog::Log(LOGERROR, "{}: Error looking up item {} ({})", __FUNCTION__, m_movieTitle,
69 m_movieYear);
70 m_state = DO_NOTHING;
71 return;
74 if (!m_url.HasUrls() && m_uniqueIDs.empty())
76 // empty url when it's not supposed to be..
77 // this might happen if the previously scraped item was removed from the site (see ticket #10537)
78 CLog::Log(LOGERROR, "{}: Error getting details for {} ({}) due to an empty url", __FUNCTION__,
79 m_movieTitle, m_movieYear);
81 else if (m_state == GET_DETAILS)
83 if (!GetDetails(m_uniqueIDs, m_url, m_movieDetails))
84 CLog::Log(LOGERROR, "{}: Error getting details from {}", __FUNCTION__,
85 m_url.GetFirstThumbUrl());
87 else if (m_state == GET_EPISODE_DETAILS)
89 if (!GetEpisodeDetails(m_url, m_movieDetails))
90 CLog::Log(LOGERROR, "{}: Error getting episode details from {}", __FUNCTION__,
91 m_url.GetFirstThumbUrl());
93 else if (m_state == GET_EPISODE_LIST)
95 if (!GetEpisodeList(m_url, m_episode))
96 CLog::Log(LOGERROR, "{}: Error getting episode list from {}", __FUNCTION__,
97 m_url.GetFirstThumbUrl());
99 m_found = 1;
100 m_state = DO_NOTHING;
103 int CVideoInfoDownloader::FindMovie(const std::string &movieTitle, int movieYear,
104 MOVIELIST& movieList,
105 CGUIDialogProgress *pProgress /* = NULL */)
107 //CLog::Log(LOGDEBUG,"CVideoInfoDownloader::FindMovie({})", strMovie);
109 if (pProgress)
110 { // threaded version
111 m_state = FIND_MOVIE;
112 m_movieTitle = movieTitle;
113 m_movieYear = movieYear;
114 m_found = 0;
115 if (IsRunning())
116 StopThread();
117 Create();
118 while (m_state != DO_NOTHING)
120 pProgress->Progress();
121 if (pProgress->IsCanceled())
123 CloseThread();
124 return 0;
126 CThread::Sleep(1ms);
128 // transfer to our movielist
129 m_movieList.swap(movieList);
130 int found=m_found;
131 CloseThread();
132 return found;
135 // unthreaded
136 int success = InternalFindMovie(movieTitle, movieYear, movieList);
137 // NOTE: this might be improved by rescraping if the match quality isn't high?
138 if (success == 1 && movieList.empty())
139 { // no results. try without cleaning chars like '.' and '_'
140 success = InternalFindMovie(movieTitle, movieYear, movieList, false);
142 return success;
145 bool CVideoInfoDownloader::GetArtwork(CVideoInfoTag &details)
147 return m_info->GetArtwork(*m_http, details);
150 bool CVideoInfoDownloader::GetDetails(const std::unordered_map<std::string, std::string>& uniqueIDs,
151 const CScraperUrl& url,
152 CVideoInfoTag& movieDetails,
153 CGUIDialogProgress* pProgress /* = NULL */)
155 //CLog::Log(LOGDEBUG,"CVideoInfoDownloader::GetDetails({})", url.m_strURL);
156 m_url = url;
157 m_uniqueIDs = uniqueIDs;
158 m_movieDetails = movieDetails;
160 // fill in the defaults
161 movieDetails.Reset();
162 if (pProgress)
163 { // threaded version
164 m_state = GET_DETAILS;
165 m_found = 0;
166 if (IsRunning())
167 StopThread();
168 Create();
169 while (!m_found)
171 pProgress->Progress();
172 if (pProgress->IsCanceled())
174 CloseThread();
175 return false;
177 CThread::Sleep(1ms);
179 movieDetails = m_movieDetails;
180 CloseThread();
181 return true;
183 else // unthreaded
184 return m_info->GetVideoDetails(*m_http, m_uniqueIDs, url, true /*fMovie*/, movieDetails);
187 bool CVideoInfoDownloader::GetEpisodeDetails(const CScraperUrl &url,
188 CVideoInfoTag &movieDetails,
189 CGUIDialogProgress *pProgress /* = NULL */)
191 //CLog::Log(LOGDEBUG,"CVideoInfoDownloader::GetDetails({})", url.m_strURL);
192 m_url = url;
193 m_movieDetails = movieDetails;
195 // fill in the defaults
196 movieDetails.Reset();
197 if (pProgress)
198 { // threaded version
199 m_state = GET_EPISODE_DETAILS;
200 m_found = 0;
201 if (IsRunning())
202 StopThread();
203 Create();
204 while (!m_found)
206 pProgress->Progress();
207 if (pProgress->IsCanceled())
209 CloseThread();
210 return false;
212 CThread::Sleep(1ms);
214 movieDetails = m_movieDetails;
215 CloseThread();
216 return true;
218 else // unthreaded
219 return m_info->GetVideoDetails(*m_http, m_uniqueIDs, url, false /*fMovie*/, movieDetails);
222 bool CVideoInfoDownloader::GetEpisodeList(const CScraperUrl& url,
223 VIDEO::EPISODELIST& movieDetails,
224 CGUIDialogProgress* pProgress /* = NULL */)
226 //CLog::Log(LOGDEBUG,"CVideoInfoDownloader::GetDetails({})", url.m_strURL);
227 m_url = url;
228 m_episode = movieDetails;
230 // fill in the defaults
231 movieDetails.clear();
232 if (pProgress)
233 { // threaded version
234 m_state = GET_EPISODE_LIST;
235 m_found = 0;
236 if (IsRunning())
237 StopThread();
238 Create();
239 while (!m_found)
241 pProgress->Progress();
242 if (pProgress->IsCanceled())
244 CloseThread();
245 return false;
247 CThread::Sleep(1ms);
249 movieDetails = m_episode;
250 CloseThread();
251 return true;
253 else // unthreaded
254 return !(movieDetails = m_info->GetEpisodeList(*m_http, url)).empty();
257 void CVideoInfoDownloader::CloseThread()
259 m_http->Cancel();
260 StopThread();
261 m_http->Reset();
262 m_state = DO_NOTHING;
263 m_found = 0;