diff --git a/include/openspace/engine/downloadmanager.h b/include/openspace/engine/downloadmanager.h index fdea67f210..a0a59d64b0 100644 --- a/include/openspace/engine/downloadmanager.h +++ b/include/openspace/engine/downloadmanager.h @@ -34,6 +34,7 @@ #include #include #include +#include namespace openspace { @@ -60,8 +61,17 @@ public: bool abortDownload; }; + struct MemoryFile { + std::string buffer; + std::string format; + }; + using DownloadProgressCallback = std::function; using DownloadFinishedCallback = std::function; + + using SuccessCallback = std::function; + using ErrorCallback = std::function; + using RequestFinishedCallback = std::function; using AsyncDownloadFinishedCallback = std::function>&)>; @@ -81,6 +91,10 @@ public: DownloadFinishedCallback finishedCallback = DownloadFinishedCallback() ); + std::future fetchFile( + const std::string& url, + SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); + std::vector> downloadRequestFiles(const std::string& identifier, const ghoul::filesystem::Directory& destination, int version, bool overrideFiles = true, diff --git a/modules/iswa/rendering/screenspacecygnet.cpp b/modules/iswa/rendering/screenspacecygnet.cpp index 12fe36f3bf..1c139e510d 100644 --- a/modules/iswa/rendering/screenspacecygnet.cpp +++ b/modules/iswa/rendering/screenspacecygnet.cpp @@ -34,17 +34,6 @@ namespace { namespace openspace { -// ScreenSpaceCygnet::ScreenSpaceCygnet(int cygnetId) -// : ScreenSpaceRenderable() -// , _updateInterval("updateInterval", "Update Interval", 1.0, 0.0 , 10.0) -// , _cygnetId(cygnetId) -// { -// setName("iSWACygnet" + std::to_string(_cygnetId)); -// addProperty(_updateInterval); - -// registerProperties(); -// } - ScreenSpaceCygnet::ScreenSpaceCygnet(const ghoul::Dictionary& dictionary) : ScreenSpaceRenderable(dictionary) , _updateInterval("updateInterval", "Update Interval", 1.0, 0.0 , 10.0) @@ -91,7 +80,6 @@ bool ScreenSpaceCygnet::deinitialize(){ _shader = nullptr; } - _memorybuffer = ""; return true; } @@ -119,9 +107,8 @@ void ScreenSpaceCygnet::update(){ _lastUpdateRealTime = _realTime; } - if(_futureTexture && _futureTexture->isFinished){ + if(_futureImage.valid() && _futureImage.wait_for(std::chrono::seconds(0)) == std::future_status::ready){ loadTexture(); - _futureTexture = nullptr; } } @@ -135,32 +122,25 @@ bool ScreenSpaceCygnet::isReady() const{ } void ScreenSpaceCygnet::updateTexture(){ - // If a download is in progress, dont send another request. - if(_futureTexture && !_futureTexture->isFinished && !_futureTexture->isAborted) + std::cout << "updateTexture begin" << std::endl; + if(_futureImage.valid() && _futureImage.wait_for(std::chrono::seconds(0)) == std::future_status::timeout) return; - _memorybuffer = ""; - std::shared_ptr future = ISWAManager::ref().downloadImageToMemory(_cygnetId, _memorybuffer); - if(future){ - _futureTexture = future; + std::future future = ISWAManager::ref().fetchCygnet(_cygnetId); + if(future.valid()){ + _futureImage = std::move(future); } - } void ScreenSpaceCygnet::loadTexture() { - if(_memorybuffer != ""){ - - std::string format; - std::stringstream ss(_futureTexture->format); - getline(ss, format ,'/'); - getline(ss, format); + try { + DownloadManager::MemoryFile imageFile = _futureImage.get(); std::unique_ptr texture = ghoul::io::TextureReader::ref().loadTexture( - (void*) _memorybuffer.c_str(), - _memorybuffer.size(), - format); - // std::unique_ptr texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_path)); + (void*) imageFile.buffer.c_str(), + imageFile.buffer.size(), + imageFile.format); if (texture) { // LDEBUG("Loaded texture from '" << absPath(_path) << "'"); @@ -171,6 +151,9 @@ void ScreenSpaceCygnet::loadTexture() { _texture = std::move(texture); } + + } catch( std::exception& e ) { + LWARNING( "ScreenSpaceCygnet futureImage exception: " + std::string(e.what()) ); } } } \ No newline at end of file diff --git a/modules/iswa/rendering/screenspacecygnet.h b/modules/iswa/rendering/screenspacecygnet.h index 60d4ff8c75..752855964b 100644 --- a/modules/iswa/rendering/screenspacecygnet.h +++ b/modules/iswa/rendering/screenspacecygnet.h @@ -26,6 +26,7 @@ #define __SCREENSPACECYGNET_H__ #include +#include #include #include #include @@ -54,8 +55,7 @@ private: std::chrono::milliseconds _realTime; std::chrono::milliseconds _lastUpdateRealTime; - std::shared_ptr _futureTexture; - std::string _memorybuffer; + std::future _futureImage; }; } // namespace openspace diff --git a/modules/iswa/util/iswamanager.cpp b/modules/iswa/util/iswamanager.cpp index 0ca08bf292..392e54869b 100644 --- a/modules/iswa/util/iswamanager.cpp +++ b/modules/iswa/util/iswamanager.cpp @@ -190,6 +190,18 @@ std::shared_ptr ISWAManager::downloadDataToMemory(i ); } +std::future ISWAManager::fetchCygnet(int id){ + return std::move( DlManager.fetchFile( + iSWAurl(id, "image"), + [](const DownloadManager::MemoryFile& file){ + LDEBUG("Download to memory finished"); + }, + [](const std::string& err){ + LDEBUG("Download to memory was aborted: " + err); + } + ) ); +} + std::string ISWAManager::iSWAurl(int id, std::string type){ std::string url; diff --git a/modules/iswa/util/iswamanager.h b/modules/iswa/util/iswamanager.h index d3973a31c6..5120111361 100644 --- a/modules/iswa/util/iswamanager.h +++ b/modules/iswa/util/iswamanager.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -75,6 +76,8 @@ public: std::shared_ptr downloadImageToMemory(int id, std::string& buffer); std::shared_ptr downloadDataToMemory(int id, std::string& buffer); + std::future fetchCygnet(int id); + void registerGroup(int id); void registerToGroup(int id, CygnetType type, ISWACygnet* cygnet); diff --git a/src/engine/downloadmanager.cpp b/src/engine/downloadmanager.cpp index 2628741de4..b0cda1ed15 100644 --- a/src/engine/downloadmanager.cpp +++ b/src/engine/downloadmanager.cpp @@ -262,6 +262,54 @@ std::shared_ptr DownloadManager::downloadToMemory( return future; } +std::future DownloadManager::fetchFile( + const std::string& url, + SuccessCallback successCallback, ErrorCallback errorCallback) +{ + LDEBUG("Start downloading file: '" << url << "' into memory"); + + auto downloadFunction = [url, successCallback, errorCallback]() { + DownloadManager::MemoryFile file; + CURL* curl = curl_easy_init(); + if (curl) { + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file.buffer); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeToMemory); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); + + CURLcode res = curl_easy_perform(curl); + if(res == CURLE_OK){ + // ask for the content-type + char *ct; + res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); + if(res == CURLE_OK){ + std::string extension = std::string(ct); + std::stringstream ss(extension); + getline(ss, extension ,'/'); + getline(ss, extension); + file.format = extension; + } else{ + LWARNING("Could not get File extension from file downloaded from: " + url); + } + successCallback(file); + curl_easy_cleanup(curl); + return std::move(file); + } else { + std::string err = curl_easy_strerror(res); + errorCallback(err); + curl_easy_cleanup(curl); + // Throw an error and use try-catch around future.get() call + throw std::runtime_error( err ); + // or set a boolean variable in MemoryFile to determine if it is valid/corrupted or not. + // Return MemoryFile even if it is not valid, and check if it is after future.get() call. + } + } + }; + + return std::move( std::async(std::launch::async, downloadFunction) ); +} + std::vector> DownloadManager::downloadRequestFiles( const std::string& identifier, const ghoul::filesystem::Directory& destination, int version, bool overrideFiles, DownloadFinishedCallback finishedCallback,