Fixed an issue where the wrong thumbnail could be displayed in the scraper.

This commit is contained in:
Leon Styhre 2020-11-14 20:46:08 +01:00
parent 2b189f9d19
commit 4fb12a4801
4 changed files with 43 additions and 33 deletions

View file

@ -140,8 +140,8 @@ GuiScraperSearch::~GuiScraperSearch()
if (mMDResolveHandle) if (mMDResolveHandle)
mMDResolveHandle.reset(); mMDResolveHandle.reset();
if (mThumbnailReq) if (mThumbnailReqMap.size() > 0)
mThumbnailReq.reset(); mThumbnailReqMap.clear();
HttpReq::cleanupCurlMulti(); HttpReq::cleanupCurlMulti();
} }
@ -287,7 +287,7 @@ void GuiScraperSearch::search(const ScraperSearchParams& params)
mResultList->clear(); mResultList->clear();
mScraperResults.clear(); mScraperResults.clear();
mMDRetrieveURLsHandle.reset(); mMDRetrieveURLsHandle.reset();
mThumbnailReq.reset(); mThumbnailReqMap.clear();
mMDResolveHandle.reset(); mMDResolveHandle.reset();
updateInfoPane(); updateInfoPane();
@ -297,7 +297,7 @@ void GuiScraperSearch::search(const ScraperSearchParams& params)
void GuiScraperSearch::stop() void GuiScraperSearch::stop()
{ {
mThumbnailReq.reset(); mThumbnailReqMap.clear();
mSearchHandle.reset(); mSearchHandle.reset();
mMDResolveHandle.reset(); mMDResolveHandle.reset();
mMDRetrieveURLsHandle.reset(); mMDRetrieveURLsHandle.reset();
@ -353,14 +353,14 @@ void GuiScraperSearch::onSearchDone(const std::vector<ScraperSearchResult>& resu
// If there is no thumbnail to download and we're in semi-automatic mode, proceed to return // If there is no thumbnail to download and we're in semi-automatic mode, proceed to return
// the results or we'll get stuck forever waiting for a thumbnail to be downloaded. // the results or we'll get stuck forever waiting for a thumbnail to be downloaded.
if (mSearchType == ACCEPT_SINGLE_MATCHES && results.size() == 1 && if (mSearchType == ACCEPT_SINGLE_MATCHES && results.size() == 1 &&
mScraperResults.front().ThumbnailImageUrl == "") mScraperResults.front().thumbnailImageUrl == "")
returnResult(mScraperResults.front()); returnResult(mScraperResults.front());
// For automatic mode, if there's no thumbnail to download or no matching games found, // For automatic mode, if there's no thumbnail to download or no matching games found,
// proceed directly or we'll get stuck forever. // proceed directly or we'll get stuck forever.
if (mSearchType == ALWAYS_ACCEPT_FIRST_RESULT) { if (mSearchType == ALWAYS_ACCEPT_FIRST_RESULT) {
if (mScraperResults.size() == 0 || (mScraperResults.size() > 0 && if (mScraperResults.size() == 0 || (mScraperResults.size() > 0 &&
mScraperResults.front().ThumbnailImageUrl == "")) { mScraperResults.front().thumbnailImageUrl == "")) {
if (mScraperResults.size() == 0) if (mScraperResults.size() == 0)
mSkipCallback(); mSkipCallback();
else else
@ -423,12 +423,12 @@ void GuiScraperSearch::updateInfoPane()
mResultThumbnail->setImage(""); mResultThumbnail->setImage("");
const std::string& thumb = res.screenshotUrl.empty() ? res.coverUrl : res.screenshotUrl; const std::string& thumb = res.screenshotUrl.empty() ? res.coverUrl : res.screenshotUrl;
mScraperResults[i].ThumbnailImageUrl = thumb; mScraperResults[i].thumbnailImageUrl = thumb;
// Cache the thumbnail image in mScraperResults so that we don't need to download // Cache the thumbnail image in mScraperResults so that we don't need to download
// it every time the list is scrolled back and forth. // it every time the list is scrolled back and forth.
if (mScraperResults[i].ThumbnailImageData.size() > 0) { if (mScraperResults[i].thumbnailImageData.size() > 0) {
std::string content = mScraperResults[i].ThumbnailImageData; std::string content = mScraperResults[i].thumbnailImageData;
mResultThumbnail->setImage(content.data(), content.length()); mResultThumbnail->setImage(content.data(), content.length());
mGrid.onSizeChanged(); // A hack to fix the thumbnail position since its size changed. mGrid.onSizeChanged(); // A hack to fix the thumbnail position since its size changed.
} }
@ -437,14 +437,16 @@ void GuiScraperSearch::updateInfoPane()
else { else {
if (!thumb.empty()) { if (!thumb.empty()) {
// Make sure we don't attempt to download the same thumbnail twice. // Make sure we don't attempt to download the same thumbnail twice.
if (!mThumbnailReq && mScraperResults[i].thumbnailDownloadStatus != IN_PROGRESS) { if (mScraperResults[i].thumbnailDownloadStatus != IN_PROGRESS) {
mScraperResults[i].thumbnailDownloadStatus = IN_PROGRESS; mScraperResults[i].thumbnailDownloadStatus = IN_PROGRESS;
mThumbnailReq = std::unique_ptr<HttpReq>(new HttpReq(thumb)); // Add an entry into the thumbnail map, this way we can track and download
// each thumbnail separately even as they're downloading while scrolling
// through the result list.
mThumbnailReqMap.insert(std::pair<std::string,
std::unique_ptr<HttpReq>>(mScraperResults[i].thumbnailImageUrl,
std::unique_ptr<HttpReq>(new HttpReq(thumb))));
} }
} }
else {
mThumbnailReq.reset();
}
} }
// Metadata. // Metadata.
@ -528,8 +530,13 @@ void GuiScraperSearch::update(int deltaTime)
if (mBlockAccept) if (mBlockAccept)
mBusyAnim.update(deltaTime); mBusyAnim.update(deltaTime);
if (mThumbnailReq && mThumbnailReq->status() != HttpReq::REQ_IN_PROGRESS) // Check if the thumbnail for the currently selected game has finished downloading.
updateThumbnail(); if (mScraperResults.size() > 0) {
auto it = mThumbnailReqMap.find(mScraperResults[mResultList->
getCursorId()].thumbnailImageUrl);
if (it != mThumbnailReqMap.end() && it->second->status() != HttpReq::REQ_IN_PROGRESS)
updateThumbnail();
}
if (mSearchHandle && mSearchHandle->status() != ASYNC_IN_PROGRESS) { if (mSearchHandle && mSearchHandle->status() != ASYNC_IN_PROGRESS) {
auto status = mSearchHandle->status(); auto status = mSearchHandle->status();
@ -610,26 +617,29 @@ void GuiScraperSearch::update(int deltaTime)
void GuiScraperSearch::updateThumbnail() void GuiScraperSearch::updateThumbnail()
{ {
if (mThumbnailReq && mThumbnailReq->status() == HttpReq::REQ_SUCCESS) { auto it = mThumbnailReqMap.find(mScraperResults[mResultList->getCursorId()].thumbnailImageUrl);
if (it != mThumbnailReqMap.end() && it->second->status() == HttpReq::REQ_SUCCESS) {
// Save thumbnail to mScraperResults cache and set the flag that the // Save thumbnail to mScraperResults cache and set the flag that the
// thumbnail download has been completed for this game. // thumbnail download has been completed for this game.
for (auto i = 0; i < mScraperResults.size(); i++) { if (mScraperResults[mResultList->getCursorId()].thumbnailDownloadStatus == IN_PROGRESS) {
if (mScraperResults[i].thumbnailDownloadStatus == IN_PROGRESS) { mScraperResults[mResultList->getCursorId()].thumbnailImageData =
mScraperResults[i].ThumbnailImageData = mThumbnailReq->getContent(); it->second->getContent();
mScraperResults[i].thumbnailDownloadStatus = COMPLETED; mScraperResults[mResultList->getCursorId()].thumbnailDownloadStatus = COMPLETED;
}
} }
// Activate the thumbnail in the GUI. // Activate the thumbnail in the GUI.
std::string content = mThumbnailReq->getContent(); std::string content = mScraperResults[mResultList->getCursorId()].thumbnailImageData;
mResultThumbnail->setImage(content.data(), content.length()); if (content.size() > 0) {
mGrid.onSizeChanged(); // A hack to fix the thumbnail position since its size changed. mResultThumbnail->setImage(content.data(), content.length());
mGrid.onSizeChanged(); // A hack to fix the thumbnail position since its size changed.
}
} }
else { else {
LOG(LogWarning) << "thumbnail req failed: " << mThumbnailReq->getErrorMsg(); LOG(LogWarning) << "Thumbnail download failed: " << it->second->getErrorMsg();
mResultThumbnail->setImage(""); mResultThumbnail->setImage("");
} }
mThumbnailReq.reset(); mThumbnailReqMap.erase(it);
// When the thumbnail has been downloaded and we are in automatic mode, or if // When the thumbnail has been downloaded and we are in automatic mode, or if
// we are in semi-automatic mode with a single matching game result, we proceed // we are in semi-automatic mode with a single matching game result, we proceed

View file

@ -127,7 +127,7 @@ private:
std::unique_ptr<ScraperSearchHandle> mMDRetrieveURLsHandle; std::unique_ptr<ScraperSearchHandle> mMDRetrieveURLsHandle;
std::unique_ptr<MDResolveHandle> mMDResolveHandle; std::unique_ptr<MDResolveHandle> mMDResolveHandle;
std::vector<ScraperSearchResult> mScraperResults; std::vector<ScraperSearchResult> mScraperResults;
std::unique_ptr<HttpReq> mThumbnailReq; std::map<std::string, std::unique_ptr<HttpReq>> mThumbnailReqMap;
BusyComponent mBusyAnim; BusyComponent mBusyAnim;
}; };

View file

@ -239,8 +239,8 @@ MDResolveHandle::MDResolveHandle(const ScraperSearchResult& result,
// If the image is cached already as the thumbnail, then we don't need // If the image is cached already as the thumbnail, then we don't need
// to download it again, in this case just save it to disk and resize it. // to download it again, in this case just save it to disk and resize it.
if (mResult.ThumbnailImageUrl == it->fileURL && if (mResult.thumbnailImageUrl == it->fileURL &&
mResult.ThumbnailImageData.size() > 0) { mResult.thumbnailImageData.size() > 0) {
// Remove any existing media file before attempting to write a new one. // Remove any existing media file before attempting to write a new one.
// This avoids the problem where there's already a file for this media type // This avoids the problem where there's already a file for this media type
@ -268,7 +268,7 @@ MDResolveHandle::MDResolveHandle(const ScraperSearchResult& result,
return; return;
} }
const std::string& content = mResult.ThumbnailImageData; const std::string& content = mResult.thumbnailImageData;
stream.write(content.data(), content.length()); stream.write(content.data(), content.length());
stream.close(); stream.close();
if (stream.bad()) { if (stream.bad()) {

View file

@ -53,8 +53,8 @@ struct ScraperSearchResult {
enum downloadStatus thumbnailDownloadStatus = NOT_STARTED; enum downloadStatus thumbnailDownloadStatus = NOT_STARTED;
enum downloadStatus mediaFilesDownloadStatus = NOT_STARTED; enum downloadStatus mediaFilesDownloadStatus = NOT_STARTED;
std::string ThumbnailImageData; // Thumbnail cache, will contain entire image. std::string thumbnailImageData; // Thumbnail cache, this will contain the entire image.
std::string ThumbnailImageUrl; std::string thumbnailImageUrl;
std::string box3dUrl; std::string box3dUrl;
std::string coverUrl; std::string coverUrl;