mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 06:05:38 +00:00
Replaced AsyncReqComponent with some handles.
UI is no longer completely blocked during asynchronous operations.
This commit is contained in:
parent
dbde900629
commit
1e8b040f73
|
@ -135,6 +135,7 @@ endif()
|
|||
#-------------------------------------------------------------------------------
|
||||
#define basic sources and headers
|
||||
set(ES_HEADERS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/AsyncHandle.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/AudioManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/EmulationStation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/FileData.h
|
||||
|
|
43
src/AsyncHandle.h
Normal file
43
src/AsyncHandle.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
enum AsyncHandleStatus
|
||||
{
|
||||
ASYNC_IN_PROGRESS,
|
||||
ASYNC_ERROR,
|
||||
ASYNC_DONE
|
||||
};
|
||||
|
||||
// Handle for some asynchronous operation.
|
||||
class AsyncHandle
|
||||
{
|
||||
public:
|
||||
AsyncHandle() : mStatus(ASYNC_IN_PROGRESS) {};
|
||||
|
||||
virtual void update() = 0;
|
||||
|
||||
// Update and return the latest status.
|
||||
inline AsyncHandleStatus status() { update(); return mStatus; }
|
||||
|
||||
// User-friendly string of our current status. Will return error message if status() == SEARCH_ERROR.
|
||||
inline std::string getStatusString()
|
||||
{
|
||||
switch(mStatus)
|
||||
{
|
||||
case ASYNC_IN_PROGRESS:
|
||||
return "in progress";
|
||||
case ASYNC_ERROR:
|
||||
return mError;
|
||||
case ASYNC_DONE:
|
||||
return "done";
|
||||
default:
|
||||
return "something impossible has occured; row, row, fight the power";
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void setStatus(AsyncHandleStatus status) { mStatus = status; }
|
||||
inline void setError(const std::string& error) { setStatus(ASYNC_ERROR); mError = error; }
|
||||
|
||||
std::string mError;
|
||||
AsyncHandleStatus mStatus;
|
||||
};
|
|
@ -144,14 +144,9 @@ HttpReq::Status HttpReq::status()
|
|||
return mStatus;
|
||||
}
|
||||
|
||||
std::string HttpReq::getContent()
|
||||
std::string HttpReq::getContent() const
|
||||
{
|
||||
if(mStatus != REQ_SUCCESS)
|
||||
{
|
||||
LOG(LogError) << "Called getContent() on an incomplete HttpReq!";
|
||||
return "";
|
||||
}
|
||||
|
||||
assert(mStatus == REQ_SUCCESS);
|
||||
return mContent.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
std::string getErrorMsg();
|
||||
|
||||
std::string getContent();
|
||||
std::string getContent() const; // mStatus must be REQ_SUCCESS
|
||||
|
||||
static std::string urlEncode(const std::string &s);
|
||||
static bool isUrl(const std::string& s);
|
||||
|
|
|
@ -116,6 +116,8 @@ void ComponentList::onCursorChanged(const CursorState& state)
|
|||
mCameraOffset = 0;
|
||||
else if(mCameraOffset + mSize.y() > totalHeight)
|
||||
mCameraOffset = totalHeight - mSize.y();
|
||||
}else{
|
||||
mCameraOffset = 0;
|
||||
}
|
||||
|
||||
updateHelpPrompts();
|
||||
|
|
|
@ -259,7 +259,7 @@ private:
|
|||
ss << getSelectedObjects().size() << " SELECTED";
|
||||
mText.setText(ss.str());
|
||||
mText.setSize(0, mText.getSize().y());
|
||||
setSize(mText.getSize().x() + mRightArrow.getSize().x() + 16, mText.getSize().y());
|
||||
setSize(mText.getSize().x() + mRightArrow.getSize().x() + 24, mText.getSize().y());
|
||||
if(mParent) // hack since theres no "on child size changed" callback atm...
|
||||
mParent->onSizeChanged();
|
||||
}else{
|
||||
|
@ -270,7 +270,7 @@ private:
|
|||
{
|
||||
mText.setText(strToUpper(it->name));
|
||||
mText.setSize(0, mText.getSize().y());
|
||||
setSize(mText.getSize().x() + mLeftArrow.getSize().x() + mRightArrow.getSize().x() + 16, mText.getSize().y());
|
||||
setSize(mText.getSize().x() + mLeftArrow.getSize().x() + mRightArrow.getSize().x() + 24, mText.getSize().y());
|
||||
if(mParent) // hack since theres no "on child size changed" callback atm...
|
||||
mParent->onSizeChanged();
|
||||
break;
|
||||
|
|
|
@ -15,6 +15,8 @@ ScraperSearchComponent::ScraperSearchComponent(Window* window, SearchType type)
|
|||
{
|
||||
addChild(&mGrid);
|
||||
|
||||
mBlockAccept = false;
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
// left spacer (empty component, needed for borders)
|
||||
|
@ -87,6 +89,8 @@ void ScraperSearchComponent::search(const ScraperSearchParams& params)
|
|||
{
|
||||
mResultList->clear();
|
||||
mScraperResults.clear();
|
||||
mThumbnailReq.reset();
|
||||
mMDResolveHandle.reset();
|
||||
updateInfoPane();
|
||||
|
||||
mLastSearch = params;
|
||||
|
@ -120,6 +124,7 @@ void ScraperSearchComponent::onSearchDone(const std::vector<ScraperSearchResult>
|
|||
mGrid.resetCursor();
|
||||
}
|
||||
|
||||
mBlockAccept = false;
|
||||
updateInfoPane();
|
||||
|
||||
if(mSearchType == ALWAYS_ACCEPT_FIRST_RESULT)
|
||||
|
@ -177,6 +182,9 @@ bool ScraperSearchComponent::input(InputConfig* config, Input input)
|
|||
{
|
||||
if(config->isMappedTo("a", input) && input.value != 0)
|
||||
{
|
||||
if(mBlockAccept)
|
||||
return true;
|
||||
|
||||
//if you're on a result
|
||||
if(getSelectedIndex() != -1)
|
||||
{
|
||||
|
@ -195,24 +203,28 @@ bool ScraperSearchComponent::input(InputConfig* config, Input input)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void ScraperSearchComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
|
||||
if(mBlockAccept)
|
||||
{
|
||||
Renderer::setMatrix(trans);
|
||||
Renderer::drawRect((int)mResultList->getPosition().x(), (int)mResultList->getPosition().y(),
|
||||
(int)mResultList->getSize().x(), (int)mResultList->getSize().y(), 0x00000011);
|
||||
}
|
||||
|
||||
renderChildren(trans);
|
||||
}
|
||||
|
||||
void ScraperSearchComponent::returnResult(ScraperSearchResult result)
|
||||
{
|
||||
mBlockAccept = true;
|
||||
|
||||
// resolve metadata image before returning
|
||||
if(!result.imageUrl.empty())
|
||||
{
|
||||
downloadImageAsync(mWindow, result.imageUrl, getSaveAsPath(mLastSearch, "image", result.imageUrl),
|
||||
[this, result] (std::string filePath) mutable -> void
|
||||
{
|
||||
if(filePath.empty())
|
||||
{
|
||||
onSearchError("Error downloading boxart.");
|
||||
return;
|
||||
}
|
||||
|
||||
result.mdl.set("image", filePath);
|
||||
result.imageUrl = "";
|
||||
this->returnResult(result); // re-enter this function
|
||||
});
|
||||
mMDResolveHandle = resolveMetaDataAssets(result, mLastSearch);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -226,19 +238,30 @@ void ScraperSearchComponent::update(int deltaTime)
|
|||
updateThumbnail();
|
||||
}
|
||||
|
||||
if(mSearchHandle && mSearchHandle->status() != SEARCH_IN_PROGRESS)
|
||||
if(mSearchHandle && mSearchHandle->status() != ASYNC_IN_PROGRESS)
|
||||
{
|
||||
if(mSearchHandle->status() == SEARCH_DONE)
|
||||
if(mSearchHandle->status() == ASYNC_DONE)
|
||||
{
|
||||
onSearchDone(mSearchHandle->getResults());
|
||||
}else if(mSearchHandle->status() == SEARCH_ERROR)
|
||||
}else if(mSearchHandle->status() == ASYNC_ERROR)
|
||||
{
|
||||
onSearchError(mSearchHandle->getStatusString());
|
||||
}
|
||||
|
||||
mSearchHandle.reset();
|
||||
}
|
||||
|
||||
if(mMDResolveHandle && mMDResolveHandle->status() != ASYNC_IN_PROGRESS)
|
||||
{
|
||||
if(mMDResolveHandle->status() == ASYNC_DONE)
|
||||
{
|
||||
returnResult(mMDResolveHandle->getResult());
|
||||
}else if(mMDResolveHandle->status() == ASYNC_ERROR)
|
||||
{
|
||||
onSearchError(mMDResolveHandle->getStatusString());
|
||||
}
|
||||
mMDResolveHandle.reset();
|
||||
}
|
||||
|
||||
GuiComponent::update(deltaTime);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
|
||||
bool input(InputConfig* config, Input input) override;
|
||||
void update(int deltaTime) override;
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
std::vector<HelpPrompt> getHelpPrompts() override;
|
||||
void onSizeChanged() override;
|
||||
void onFocusGained() override;
|
||||
|
@ -65,8 +66,10 @@ private:
|
|||
std::function<void(const ScraperSearchResult&)> mAcceptCallback;
|
||||
std::function<void()> mSkipCallback;
|
||||
std::function<void()> mCancelCallback;
|
||||
bool mBlockAccept;
|
||||
|
||||
std::unique_ptr<ScraperSearchHandle> mSearchHandle;
|
||||
std::unique_ptr<MDResolveHandle> mMDResolveHandle;
|
||||
std::vector<ScraperSearchResult> mScraperResults;
|
||||
std::unique_ptr<HttpReq> mThumbnailReq;
|
||||
};
|
||||
|
|
|
@ -79,11 +79,14 @@ std::unique_ptr<ScraperSearchHandle> GamesDBScraper::getResultsAsync(const Scrap
|
|||
GamesDBHandle::GamesDBHandle(const ScraperSearchParams& params, const std::string& url) :
|
||||
mReq(std::unique_ptr<HttpReq>(new HttpReq(url)))
|
||||
{
|
||||
setStatus(SEARCH_IN_PROGRESS);
|
||||
setStatus(ASYNC_IN_PROGRESS);
|
||||
}
|
||||
|
||||
void GamesDBHandle::update()
|
||||
{
|
||||
if(mStatus == ASYNC_DONE)
|
||||
return;
|
||||
|
||||
if(mReq->status() == HttpReq::REQ_IN_PROGRESS)
|
||||
return;
|
||||
|
||||
|
@ -156,7 +159,7 @@ void GamesDBHandle::update()
|
|||
game = game.next_sibling("Game");
|
||||
}
|
||||
|
||||
setStatus(SEARCH_DONE);
|
||||
setStatus(ASYNC_DONE);
|
||||
setResults(results);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,48 +9,116 @@
|
|||
#include "GamesDBScraper.h"
|
||||
#include "TheArchiveScraper.h"
|
||||
|
||||
std::string ScraperSearchHandle::getStatusString()
|
||||
std::shared_ptr<Scraper> createScraperByName(const std::string& name)
|
||||
{
|
||||
switch(mStatus)
|
||||
if(name == "TheGamesDB")
|
||||
return std::shared_ptr<Scraper>(new GamesDBScraper());
|
||||
else if(name == "TheArchive")
|
||||
return std::shared_ptr<Scraper>(new TheArchiveScraper());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<MDResolveHandle> resolveMetaDataAssets(const ScraperSearchResult& result, const ScraperSearchParams& search)
|
||||
{
|
||||
return std::unique_ptr<MDResolveHandle>(new MDResolveHandle(result, search));
|
||||
}
|
||||
|
||||
MDResolveHandle::MDResolveHandle(const ScraperSearchResult& result, const ScraperSearchParams& search) : mResult(result)
|
||||
{
|
||||
if(!result.imageUrl.empty())
|
||||
{
|
||||
case SEARCH_IN_PROGRESS:
|
||||
return "search in progress";
|
||||
case SEARCH_ERROR:
|
||||
return mError;
|
||||
case SEARCH_DONE:
|
||||
return "search done";
|
||||
default:
|
||||
return "something impossible has occured";
|
||||
std::string imgPath = getSaveAsPath(search, "image", result.imageUrl);
|
||||
mFuncs.push_back(ResolvePair(downloadImageAsync(result.imageUrl, imgPath), [this, imgPath]
|
||||
{
|
||||
mResult.mdl.set("image", imgPath);
|
||||
mResult.imageUrl = "";
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
std::string processFileDownload(std::shared_ptr<HttpReq> r, std::string saveAs)
|
||||
void MDResolveHandle::update()
|
||||
{
|
||||
if(r->status() != HttpReq::REQ_SUCCESS)
|
||||
if(mStatus == ASYNC_DONE || mStatus == ASYNC_ERROR)
|
||||
return;
|
||||
|
||||
auto it = mFuncs.begin();
|
||||
while(it != mFuncs.end())
|
||||
{
|
||||
LOG(LogError) << "Failed to download file - HttpReq error: " << r->getErrorMsg();
|
||||
return "";
|
||||
if(it->first->status() == ASYNC_ERROR)
|
||||
{
|
||||
setError(it->first->getStatusString());
|
||||
return;
|
||||
}else if(it->first->status() == ASYNC_DONE)
|
||||
{
|
||||
it->second();
|
||||
it = mFuncs.erase(it);
|
||||
continue;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
std::ofstream stream(saveAs, std::ios_base::out | std::ios_base::binary);
|
||||
if(stream.fail())
|
||||
if(mFuncs.empty())
|
||||
setStatus(ASYNC_DONE);
|
||||
}
|
||||
|
||||
std::unique_ptr<AsyncHandle> downloadImageAsync(const std::string& url, const std::string& saveAs)
|
||||
{
|
||||
return std::unique_ptr<ImageDownloadHandle>(new ImageDownloadHandle(url, saveAs,
|
||||
Settings::getInstance()->getInt("ScraperResizeWidth"), Settings::getInstance()->getInt("ScraperResizeHeight")));
|
||||
}
|
||||
|
||||
ImageDownloadHandle::ImageDownloadHandle(const std::string& url, const std::string& path, int maxWidth, int maxHeight) :
|
||||
mSavePath(path), mMaxWidth(maxWidth), mMaxHeight(maxHeight), mReq(new HttpReq(url))
|
||||
{
|
||||
}
|
||||
|
||||
void ImageDownloadHandle::update()
|
||||
{
|
||||
if(mReq->status() == HttpReq::REQ_IN_PROGRESS)
|
||||
return;
|
||||
|
||||
if(mReq->status() != HttpReq::REQ_SUCCESS)
|
||||
{
|
||||
LOG(LogError) << "Failed to open \"" << saveAs << "\" for writing downloaded file.";
|
||||
return "";
|
||||
std::stringstream ss;
|
||||
ss << "Network error: " << mReq->getErrorMsg();
|
||||
setError(ss.str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::string content = r->getContent();
|
||||
// download is done, save it to disk
|
||||
std::ofstream stream(mSavePath, std::ios_base::out | std::ios_base::binary);
|
||||
if(stream.bad())
|
||||
{
|
||||
setError("Failed to open image path to write. Permission error? Disk full?");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string& content = mReq->getContent();
|
||||
stream.write(content.data(), content.length());
|
||||
stream.close();
|
||||
if(stream.bad())
|
||||
{
|
||||
setError("Failed to save image. Disk full?");
|
||||
return;
|
||||
}
|
||||
|
||||
return saveAs;
|
||||
// resize it
|
||||
if(!resizeImage(mSavePath, mMaxWidth, mMaxHeight))
|
||||
{
|
||||
setError("Error saving resized image. Out of memory? Disk full?");
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(ASYNC_DONE);
|
||||
}
|
||||
|
||||
//you can pass 0 for width or height to keep aspect ratio
|
||||
void resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
||||
bool resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
||||
{
|
||||
// nothing to do
|
||||
if(maxWidth == 0 && maxHeight == 0)
|
||||
return;
|
||||
return true;
|
||||
|
||||
FREE_IMAGE_FORMAT format = FIF_UNKNOWN;
|
||||
FIBITMAP* image = NULL;
|
||||
|
@ -62,7 +130,7 @@ void resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
|||
if(format == FIF_UNKNOWN)
|
||||
{
|
||||
LOG(LogError) << "Error - could not detect filetype for image \"" << path << "\"!";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
//make sure we can read this filetype first, then load it
|
||||
|
@ -71,7 +139,7 @@ void resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
|||
image = FreeImage_Load(format, path.c_str());
|
||||
}else{
|
||||
LOG(LogError) << "Error - file format reading not supported for image \"" << path << "\"!";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
float width = (float)FreeImage_GetWidth(image);
|
||||
|
@ -91,43 +159,16 @@ void resizeImage(const std::string& path, int maxWidth, int maxHeight)
|
|||
if(imageRescaled == NULL)
|
||||
{
|
||||
LOG(LogError) << "Could not resize image! (not enough memory? invalid bitdepth?)";
|
||||
return;
|
||||
}
|
||||
|
||||
if(!FreeImage_Save(format, imageRescaled, path.c_str()))
|
||||
{
|
||||
LOG(LogError) << "Failed to save resized image!";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool saved = FreeImage_Save(format, imageRescaled, path.c_str());
|
||||
FreeImage_Unload(imageRescaled);
|
||||
}
|
||||
|
||||
void downloadImageAsync(Window* window, const std::string& url, const std::string& saveAs, std::function<void(std::string)> returnFunc)
|
||||
{
|
||||
std::shared_ptr<HttpReq> httpreq = std::make_shared<HttpReq>(url);
|
||||
AsyncReqComponent* req = new AsyncReqComponent(window, httpreq,
|
||||
[returnFunc, saveAs] (std::shared_ptr<HttpReq> r)
|
||||
{
|
||||
std::string file = processFileDownload(r, saveAs);
|
||||
if(!file.empty())
|
||||
resizeImage(file, Settings::getInstance()->getInt("ScraperResizeWidth"), Settings::getInstance()->getInt("ScraperResizeHeight"));
|
||||
returnFunc(file);
|
||||
}, NULL);
|
||||
if(!saved)
|
||||
LOG(LogError) << "Failed to save resized image!";
|
||||
|
||||
window->pushGui(req);
|
||||
}
|
||||
|
||||
std::string downloadImage(const std::string& url, const std::string& saveAs)
|
||||
{
|
||||
std::shared_ptr<HttpReq> httpreq = std::make_shared<HttpReq>(url);
|
||||
while(httpreq->status() == HttpReq::REQ_IN_PROGRESS);
|
||||
|
||||
std::string file = processFileDownload(httpreq, saveAs);
|
||||
|
||||
if(!file.empty())
|
||||
resizeImage(file, Settings::getInstance()->getInt("ScraperResizeWidth"), Settings::getInstance()->getInt("ScraperResizeHeight"));
|
||||
|
||||
return file;
|
||||
return saved;
|
||||
}
|
||||
|
||||
std::string getSaveAsPath(const ScraperSearchParams& params, const std::string& suffix, const std::string& url)
|
||||
|
@ -153,42 +194,3 @@ std::string getSaveAsPath(const ScraperSearchParams& params, const std::string&
|
|||
path += name + ext;
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Scraper> createScraperByName(const std::string& name)
|
||||
{
|
||||
if(name == "TheGamesDB")
|
||||
return std::shared_ptr<Scraper>(new GamesDBScraper());
|
||||
else if(name == "TheArchive")
|
||||
return std::shared_ptr<Scraper>(new TheArchiveScraper());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void resolveMetaDataAssetsAsync(Window* window, const ScraperSearchParams& params, MetaDataList mdl, std::function<void(MetaDataList)> returnFunc)
|
||||
{
|
||||
const std::vector<MetaDataDecl>& mdd = params.game->metadata.getMDD();
|
||||
for(auto it = mdd.begin(); it != mdd.end(); it++)
|
||||
{
|
||||
std::string key = it->key;
|
||||
std::string val = mdl.get(key);
|
||||
if(it->type == MD_IMAGE_PATH && HttpReq::isUrl(val))
|
||||
{
|
||||
downloadImageAsync(window, val, getSaveAsPath(params, key, val), [window, params, mdl, key, returnFunc] (std::string savedAs) mutable ->
|
||||
void
|
||||
{
|
||||
if(savedAs.empty())
|
||||
{
|
||||
//error
|
||||
LOG(LogError) << "Could not resolve image for [" << getCleanFileName(params.game->getPath()) << "]! Skipping.";
|
||||
}
|
||||
|
||||
mdl.set(key, savedAs);
|
||||
resolveMetaDataAssetsAsync(window, params, mdl, returnFunc);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
returnFunc(mdl);
|
||||
}
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
#include "../MetaData.h"
|
||||
#include "../SystemData.h"
|
||||
#include "../HttpReq.h"
|
||||
#include "../AsyncHandle.h"
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
class Window;
|
||||
|
||||
struct ScraperSearchParams
|
||||
{
|
||||
SystemData* system;
|
||||
|
@ -25,34 +24,16 @@ struct ScraperSearchResult
|
|||
std::string thumbnailUrl;
|
||||
};
|
||||
|
||||
enum ScraperSearchStatus
|
||||
{
|
||||
SEARCH_IN_PROGRESS,
|
||||
SEARCH_ERROR,
|
||||
SEARCH_DONE
|
||||
};
|
||||
|
||||
class ScraperSearchHandle
|
||||
class ScraperSearchHandle : public AsyncHandle
|
||||
{
|
||||
public:
|
||||
virtual void update() = 0;
|
||||
|
||||
// Update and return the latest status.
|
||||
inline ScraperSearchStatus status() { update(); return mStatus; }
|
||||
|
||||
// User-friendly string of our current status. Will return error message if status() == SEARCH_ERROR.
|
||||
std::string getStatusString();
|
||||
|
||||
inline const std::vector<ScraperSearchResult>& getResults() const { assert(mStatus != SEARCH_IN_PROGRESS); return mResults; }
|
||||
inline const std::vector<ScraperSearchResult>& getResults() const { assert(mStatus != ASYNC_IN_PROGRESS); return mResults; }
|
||||
|
||||
protected:
|
||||
inline void setError(const std::string& error) { setStatus(SEARCH_ERROR); mError = error; }
|
||||
inline void setStatus(ScraperSearchStatus status) { mStatus = status; }
|
||||
inline void setResults(const std::vector<ScraperSearchResult>& results) { mResults = results; }
|
||||
|
||||
private:
|
||||
std::string mError;
|
||||
ScraperSearchStatus mStatus;
|
||||
std::vector<ScraperSearchResult> mResults;
|
||||
};
|
||||
|
||||
|
@ -67,23 +48,48 @@ public:
|
|||
|
||||
std::shared_ptr<Scraper> createScraperByName(const std::string& name);
|
||||
|
||||
|
||||
// Meta data asset downloading stuff.
|
||||
class MDResolveHandle : public AsyncHandle
|
||||
{
|
||||
public:
|
||||
MDResolveHandle(const ScraperSearchResult& result, const ScraperSearchParams& search);
|
||||
|
||||
void update() override;
|
||||
inline const ScraperSearchResult& getResult() const { assert(mStatus == ASYNC_DONE); return mResult; }
|
||||
|
||||
private:
|
||||
ScraperSearchResult mResult;
|
||||
|
||||
typedef std::pair< std::unique_ptr<AsyncHandle>, std::function<void()> > ResolvePair;
|
||||
std::vector<ResolvePair> mFuncs;
|
||||
};
|
||||
|
||||
class ImageDownloadHandle : public AsyncHandle
|
||||
{
|
||||
public:
|
||||
ImageDownloadHandle(const std::string& url, const std::string& path, int maxWidth, int maxHeight);
|
||||
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<HttpReq> mReq;
|
||||
std::string mSavePath;
|
||||
int mMaxWidth;
|
||||
int mMaxHeight;
|
||||
};
|
||||
|
||||
//About the same as "~/.emulationstation/downloaded_images/[system_name]/[game_name].[url's extension]".
|
||||
//Will create the "downloaded_images" and "subdirectory" directories if they do not exist.
|
||||
std::string getSaveAsPath(const ScraperSearchParams& params, const std::string& suffix, const std::string& url);
|
||||
|
||||
//Returns the path to the downloaded file (saveAs) on completion.
|
||||
//Returns empty string if an error occured.
|
||||
//Will resize according to Settings::getInt("ScraperResizeWidth") and Settings::getInt("ScraperResizeHeight").
|
||||
std::string downloadImage(const std::string& url, const std::string& saveAs);
|
||||
std::unique_ptr<AsyncHandle> downloadImageAsync(const std::string& url, const std::string& saveAs);
|
||||
|
||||
//Returns (via returnFunc) the path to the downloaded file (saveAs) on completion.
|
||||
//Returns empty string if an error occured.
|
||||
//Will resize according to Settings::getInt("ScraperResizeWidth") and Settings::getInt("ScraperResizeHeight").
|
||||
//Same as downloadImage, just async.
|
||||
void downloadImageAsync(Window* window, const std::string& url, const std::string& saveAs, std::function<void(std::string)> returnFunc);
|
||||
|
||||
void resolveMetaDataAssetsAsync(Window* window, const ScraperSearchParams& params, MetaDataList mdl, std::function<void(MetaDataList)> returnFunc);
|
||||
// Resolves all metadata assets that need to be downloaded.
|
||||
std::unique_ptr<MDResolveHandle> resolveMetaDataAssets(const ScraperSearchResult& result, const ScraperSearchParams& search);
|
||||
|
||||
//You can pass 0 for maxWidth or maxHeight to automatically keep the aspect ratio.
|
||||
//Will overwrite the image at [path] with the new resized one.
|
||||
void resizeImage(const std::string& path, int maxWidth, int maxHeight);
|
||||
//Returns true if successful, false otherwise.
|
||||
bool resizeImage(const std::string& path, int maxWidth, int maxHeight);
|
||||
|
|
|
@ -25,12 +25,12 @@ std::unique_ptr<ScraperSearchHandle> TheArchiveScraper::getResultsAsync(const Sc
|
|||
TheArchiveHandle::TheArchiveHandle(const ScraperSearchParams& params, const std::string& url) :
|
||||
mReq(std::unique_ptr<HttpReq>(new HttpReq(url)))
|
||||
{
|
||||
setStatus(SEARCH_IN_PROGRESS);
|
||||
setStatus(ASYNC_IN_PROGRESS);
|
||||
}
|
||||
|
||||
void TheArchiveHandle::update()
|
||||
{
|
||||
if(status() == SEARCH_DONE)
|
||||
if(mStatus == ASYNC_DONE)
|
||||
return;
|
||||
|
||||
if(mReq->status() == HttpReq::REQ_IN_PROGRESS)
|
||||
|
@ -91,6 +91,6 @@ void TheArchiveHandle::update()
|
|||
game = game.next_sibling("game");
|
||||
}
|
||||
|
||||
setStatus(SEARCH_DONE);
|
||||
setStatus(ASYNC_DONE);
|
||||
setResults(results);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue