diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index 3a236edf6..93a9ef86f 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -4160,7 +4160,20 @@ void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2, glEnd(); } -void Renderer::renderProgressBar(int size, int x, int y, Font2D *font) { +void Renderer::renderProgressBar(int size, int x, int y, Font2D *font, int customWidth, string prefixLabel) { + + int currentSize = size; + int maxSize = maxProgressBar; + string renderText = intToStr(static_cast(size)) + "%"; + if(customWidth > 0) { + if(size > 0) { + currentSize = size * (customWidth / size); + } + maxSize = customWidth; + } + if(prefixLabel != "") { + renderText = prefixLabel + renderText; + } //bar glBegin(GL_QUADS); @@ -4168,26 +4181,26 @@ void Renderer::renderProgressBar(int size, int x, int y, Font2D *font) { glVertex2i(x, y); glVertex2i(x, y+10); glColor4fv(progressBarFront1.ptr()); - glVertex2i(x+size, y+10); - glVertex2i(x+size, y); + glVertex2i(x + currentSize, y+10); + glVertex2i(x + currentSize, y); glEnd(); //transp bar glEnable(GL_BLEND); glBegin(GL_QUADS); glColor4fv(progressBarBack2.ptr()); - glVertex2i(x+size, y); - glVertex2i(x+size, y+10); + glVertex2i(x + currentSize, y); + glVertex2i(x + currentSize, y+10); glColor4fv(progressBarBack1.ptr()); - glVertex2i(x+maxProgressBar, y+10); - glVertex2i(x+maxProgressBar, y); + glVertex2i(x + maxSize, y+10); + glVertex2i(x + maxSize, y); glEnd(); glDisable(GL_BLEND); //text glColor3fv(defColor.ptr()); textRenderer->begin(font); - textRenderer->render(intToStr(static_cast(size))+"%", x+maxProgressBar/2, y, true); + textRenderer->render(renderText.c_str(), x + maxSize / 2, y, true); textRenderer->end(); } diff --git a/source/glest_game/graphics/renderer.h b/source/glest_game/graphics/renderer.h index 61a03c0b2..d2f8ecf38 100644 --- a/source/glest_game/graphics/renderer.h +++ b/source/glest_game/graphics/renderer.h @@ -397,7 +397,9 @@ public: uint64 getCurrentPixelByteCount(ResourceScope rs=rsGame) const; unsigned int getSaveScreenQueueSize(); - Texture2D *saveScreenToTexture(int x, int y, int width, int height); + Texture2D *saveScreenToTexture(int x, int y, int width, int height); + + void renderProgressBar(int size, int x, int y, Font2D *font,int customWidth=-1, string prefixLabel=""); private: //private misc @@ -429,7 +431,6 @@ private: //private aux drawing void renderSelectionCircle(Vec3f v, int size, float radius); void renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &color, float width); - void renderProgressBar(int size, int x, int y, Font2D *font); void renderTile(const Vec2i &pos); void renderQuad(int x, int y, int w, int h, const Texture2D *texture); diff --git a/source/glest_game/menu/menu_state_connected_game.cpp b/source/glest_game/menu/menu_state_connected_game.cpp index 852b543a4..5f22711d1 100644 --- a/source/glest_game/menu/menu_state_connected_game.cpp +++ b/source/glest_game/menu/menu_state_connected_game.cpp @@ -453,6 +453,8 @@ void MenuStateConnectedGame::mouseClick(int x, int y, MouseButton mouseButton){ if(ftpClientThread != NULL) { ftpClientThread->addMapToRequests(getMissingMapFromFTPServer); + MutexSafeWrapper safeMutexFTPProgress(ftpClientThread->getProgressMutex()); + fileFTPProgressList[getMissingMapFromFTPServer] = pair(0,""); } } else if(ftpMissingDataType == ftpmsg_MissingTileset) { @@ -464,6 +466,8 @@ void MenuStateConnectedGame::mouseClick(int x, int y, MouseButton mouseButton){ if(ftpClientThread != NULL) { ftpClientThread->addTilesetToRequests(getMissingTilesetFromFTPServer); + MutexSafeWrapper safeMutexFTPProgress(ftpClientThread->getProgressMutex()); + fileFTPProgressList[getMissingTilesetFromFTPServer] = pair(0,""); } } } @@ -748,6 +752,23 @@ void MenuStateConnectedGame::render() { if(program != NULL) program->renderProgramMsgBox(); + MutexSafeWrapper safeMutexFTPProgress(ftpClientThread->getProgressMutex()); + if(fileFTPProgressList.size() > 0) { + int yLocation = buttonDisconnect.getY(); + for(std::map >::iterator iterMap = fileFTPProgressList.begin(); + iterMap != fileFTPProgressList.end(); ++iterMap) { + + renderer.renderProgressBar( + iterMap->second.first, + 10, + yLocation, + CoreData::getInstance().getDisplayFontSmall(), + 350,"Downloading " + iterMap->first + " [" + iterMap->second.second + "] "); + + yLocation -= 100; + } + } + safeMutexFTPProgress.ReleaseLock(); if(enableMapPreview && (mapPreview.hasFileLoaded() == true)) { @@ -1683,13 +1704,29 @@ void MenuStateConnectedGame::showFTPMessageBox(const string &text, const string } } -void MenuStateConnectedGame::FTPClient_CallbackEvent(string itemName, FTP_Client_CallbackType type, FTP_Client_ResultType result) { +void MenuStateConnectedGame::FTPClient_CallbackEvent(string itemName, FTP_Client_CallbackType type, FTP_Client_ResultType result, void *userdata) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); - if(type == ftp_cct_Map) { + if(type == ftp_cct_DownloadProgress) { + FTPClientCallbackInterface::FtpProgressStats *stats = (FTPClientCallbackInterface::FtpProgressStats *)userdata; + if(stats != NULL) { + int fileProgress = 0; + if(stats->download_total > 0) { + fileProgress = (stats->download_now * 100.0 / stats->download_total); + } + printf("Got FTP Callback for [%s] fileProgress = %d [now = %f, total = %f]\n",itemName.c_str(),fileProgress,stats->download_now,stats->download_total); + + fileFTPProgressList[itemName] = pair(fileProgress,stats->currentFilename); + } + } + else if(type == ftp_cct_Map) { getMissingMapFromFTPServerInProgress = false; printf("Got FTP Callback for [%s] result = %d\n",itemName.c_str(),result); + MutexSafeWrapper safeMutexFTPProgress(ftpClientThread->getProgressMutex()); + fileFTPProgressList.erase(itemName); + safeMutexFTPProgress.ReleaseLock(); + NetworkManager &networkManager= NetworkManager::getInstance(); ClientInterface* clientInterface= networkManager.getClientInterface(); const GameSettings *gameSettings = clientInterface->getGameSettings(); @@ -1711,6 +1748,10 @@ void MenuStateConnectedGame::FTPClient_CallbackEvent(string itemName, FTP_Client getMissingTilesetFromFTPServerInProgress = false; printf("Got FTP Callback for [%s] result = %d\n",itemName.c_str(),result); + MutexSafeWrapper safeMutexFTPProgress(ftpClientThread->getProgressMutex()); + fileFTPProgressList.erase(itemName); + safeMutexFTPProgress.ReleaseLock(); + NetworkManager &networkManager= NetworkManager::getInstance(); ClientInterface* clientInterface= networkManager.getClientInterface(); const GameSettings *gameSettings = clientInterface->getGameSettings(); @@ -1720,10 +1761,46 @@ void MenuStateConnectedGame::FTPClient_CallbackEvent(string itemName, FTP_Client sprintf(szMsg,"Player: %s SUCCESSFULLY downloaded the tileset: %s",getHumanPlayerName().c_str(),gameSettings->getTileset().c_str()); clientInterface->sendTextMessage(szMsg,-1, true); + // START + // Clear the CRC Cache if it is populated + // + vector paths = Config::getInstance().getPathListForType(ptTilesets); + string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey1; + std::map &crcTreeCache = CacheManager::getCachedItem< std::map >(cacheLookupId); + string pathSearchString = string("/") + itemName + string("/*"); + const string filterFileExt = ".xml"; + + string cacheKey = ""; + size_t count = paths.size(); + for(size_t idx = 0; idx < count; ++idx) { + string path = paths[idx] + pathSearchString; + + cacheKey += path + "_" + filterFileExt + "_"; + } + if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] CLEARING CACHED checksum for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str()); + crcTreeCache.erase(cacheKey); + } + + cacheLookupId = CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey2; + std::map &crcTreeCache2 = CacheManager::getCachedItem< std::map >(cacheLookupId); + + count = paths.size(); + for(size_t idx = 0; idx < count; ++idx) { + string path = paths[idx] + pathSearchString; + + string cacheKey = path + "_" + filterFileExt; + if(crcTreeCache2.find(cacheKey) != crcTreeCache2.end()) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] CLEARING CACHED checksum for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str()); + crcTreeCache2.erase(cacheKey); + } + } + // END + + // Reload tilesets for the UI findDirs(Config::getInstance().getPathListForType(ptTilesets), tileSets); } else { - curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW); char szMsg[1024]=""; diff --git a/source/glest_game/menu/menu_state_connected_game.h b/source/glest_game/menu/menu_state_connected_game.h index 32e4aaf04..7ef5c297b 100644 --- a/source/glest_game/menu/menu_state_connected_game.h +++ b/source/glest_game/menu/menu_state_connected_game.h @@ -151,6 +151,8 @@ private: string getMissingTilesetFromFTPServer; bool getMissingTilesetFromFTPServerInProgress; + std::map > fileFTPProgressList; + public: MenuStateConnectedGame(Program *program, MainMenu *mainMenu, JoinMenu joinMenuInfo=jmSimple, bool openNetworkSlots= false); @@ -181,7 +183,7 @@ private: void showMessageBox(const string &text, const string &header, bool toggle); void showFTPMessageBox(const string &text, const string &header, bool toggle); - virtual void FTPClient_CallbackEvent(string itemName, FTP_Client_CallbackType type, FTP_Client_ResultType result); + virtual void FTPClient_CallbackEvent(string itemName, FTP_Client_CallbackType type, FTP_Client_ResultType result,void *userdata); }; }}//end namespace diff --git a/source/shared_lib/include/platform/common/cache_manager.h b/source/shared_lib/include/platform/common/cache_manager.h index 8ccb77fed..0d19643f6 100644 --- a/source/shared_lib/include/platform/common/cache_manager.h +++ b/source/shared_lib/include/platform/common/cache_manager.h @@ -30,6 +30,13 @@ namespace Shared { namespace PlatformCommon { class CacheManager { +public: + +static const char *getFolderTreeContentsCheckSumRecursivelyCacheLookupKey1; +static const char *getFolderTreeContentsCheckSumRecursivelyCacheLookupKey2; +static const char *getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey1; +static const char *getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey2; + protected: static Mutex mutexCache; diff --git a/source/shared_lib/include/platform/posix/miniftpclient.h b/source/shared_lib/include/platform/posix/miniftpclient.h index a1651931c..2fe86b188 100644 --- a/source/shared_lib/include/platform/posix/miniftpclient.h +++ b/source/shared_lib/include/platform/posix/miniftpclient.h @@ -33,13 +33,23 @@ enum FTP_Client_ResultType { }; enum FTP_Client_CallbackType { - ftp_cct_Map = 0, - ftp_cct_Tileset = 1 + ftp_cct_Map = 0, + ftp_cct_Tileset = 1, + ftp_cct_DownloadProgress = 2 }; class FTPClientCallbackInterface { public: - virtual void FTPClient_CallbackEvent(string itemName, FTP_Client_CallbackType type, FTP_Client_ResultType result) = 0; + + struct FtpProgressStats { + double download_total; + double download_now; + double upload_total; + double upload_now; + string currentFilename; + }; + + virtual void FTPClient_CallbackEvent(string itemName, FTP_Client_CallbackType type, FTP_Client_ResultType result, void *userdata) = 0; }; class FTPClientThread : public BaseThread @@ -63,6 +73,8 @@ protected: void getTilesetFromServer(string tileSetName); FTP_Client_ResultType getTilesetFromServer(string tileSetName, string tileSetNameSubfolder, string ftpUser, string ftpUserPassword); + Mutex mutexProgressMutex; + public: FTPClientThread(int portNumber,string serverUrl, std::pair mapsPath, std::pair tilesetsPath, FTPClientCallbackInterface *pCBObject); @@ -72,6 +84,9 @@ public: void addMapToRequests(string mapFilename); void addTilesetToRequests(string tileSetName); + + FTPClientCallbackInterface * getCallBackObject() { return pCBObject; } + Mutex * getProgressMutex() { return &mutexProgressMutex; } }; }}//end namespace diff --git a/source/shared_lib/sources/platform/common/cache_manager.cpp b/source/shared_lib/sources/platform/common/cache_manager.cpp index 2adf24009..e708a6cc8 100644 --- a/source/shared_lib/sources/platform/common/cache_manager.cpp +++ b/source/shared_lib/sources/platform/common/cache_manager.cpp @@ -14,5 +14,9 @@ namespace Shared { namespace PlatformCommon { Mutex CacheManager::mutexCache; +const char *CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey1 = "CRC_Cache_FileTree1"; +const char *CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey2 = "CRC_Cache_FileTree2"; +const char *CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey1 = "CRC_Cache_FileTreeList1"; +const char *CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey2 = "CRC_Cache_FileTreeList2"; }}//end namespace diff --git a/source/shared_lib/sources/platform/common/platform_common.cpp b/source/shared_lib/sources/platform/common/platform_common.cpp index 0fc691b46..a2d4d481f 100644 --- a/source/shared_lib/sources/platform/common/platform_common.cpp +++ b/source/shared_lib/sources/platform/common/platform_common.cpp @@ -369,12 +369,8 @@ bool EndsWith(const string &str, const string& key) //finds all filenames like path and gets their checksum of all files combined int32 getFolderTreeContentsCheckSumRecursively(vector paths, string pathSearchString, const string filterFileExt, Checksum *recursiveChecksum) { - //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - - // !!! OLD local CACHE - //static std::map crcTreeCache; - string cacheLookupId = string(__FILE__) + intToStr(__LINE__); + string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey1; std::map &crcTreeCache = CacheManager::getCachedItem< std::map >(cacheLookupId); string cacheKey = ""; @@ -414,10 +410,7 @@ int32 getFolderTreeContentsCheckSumRecursively(vector paths, string path //finds all filenames like path and gets their checksum of all files combined int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path = [%s] filterFileExt = [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),filterFileExt.c_str()); - - // !!! OLD local CACHE - //static std::map crcTreeCache; - string cacheLookupId = string(__FILE__) + intToStr(__LINE__); + string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey2; std::map &crcTreeCache = CacheManager::getCachedItem< std::map >(cacheLookupId); string cacheKey = path + "_" + filterFileExt; @@ -522,10 +515,8 @@ int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string } vector > getFolderTreeContentsCheckSumListRecursively(vector paths, string pathSearchString, string filterFileExt, vector > *recursiveMap) { - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - - //static std::map > > crcTreeCache; - string cacheLookupId = string(__FILE__) + intToStr(__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey1; std::map > > &crcTreeCache = CacheManager::getCachedItem< std::map > > >(cacheLookupId); string cacheKey = ""; @@ -564,9 +555,7 @@ vector > getFolderTreeContentsCheckSumListRecursively(ve //finds all filenames like path and gets the checksum of each file vector > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector > *recursiveMap) { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path = [%s] filterFileExt = [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),filterFileExt.c_str()); - - //static std::map > > crcTreeCache; - string cacheLookupId = string(__FILE__) + intToStr(__LINE__); + string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey2; std::map > > &crcTreeCache = CacheManager::getCachedItem< std::map > > >(cacheLookupId); string cacheKey = path + "_" + filterFileExt; diff --git a/source/shared_lib/sources/platform/posix/miniftpclient.cpp b/source/shared_lib/sources/platform/posix/miniftpclient.cpp index e77dd0714..3c2d6e14e 100644 --- a/source/shared_lib/sources/platform/posix/miniftpclient.cpp +++ b/source/shared_lib/sources/platform/posix/miniftpclient.cpp @@ -32,10 +32,12 @@ namespace Shared { namespace PlatformCommon { */ struct FtpFile { + const char *itemName; const char *filename; const char *filepath; FILE *stream; FTPClientThread *ftpServer; + string currentFilename; }; static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) { @@ -88,6 +90,10 @@ static long file_is_comming(struct curl_fileinfo *finfo,void *data,int remains) if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n===> FTP Client thread file_is_comming: remains: [%3d] filename: [%s] size: [%10luB] ", remains, finfo->filename,(unsigned long)finfo->size); + if(out != NULL) { + out->currentFilename = finfo->filename; + } + switch(finfo->filetype) { case CURLFILETYPE_DIRECTORY: printf("DIR (creating [%s%s])\n",rootFilePath.c_str(),finfo->filename); @@ -131,6 +137,29 @@ static long file_is_downloaded(void *data) { return CURL_CHUNK_END_FUNC_OK; } +int file_progress(struct FtpFile *out,double download_total, double download_now, double upload_total,double upload_now) { + // printf("%d / %d (%g %%)\n", d, t, d*100.0/t); + //gdk_threads_enter(); + //gtk_progress_set_value(GTK_PROGRESS(bar), d*100.0/t); + //gdk_threads_leave(); + + if(out != NULL && + out->ftpServer != NULL && + out->ftpServer->getCallBackObject() != NULL) { + FTPClientCallbackInterface::FtpProgressStats stats; + stats.download_total = download_total; + stats.download_now = download_now; + stats.upload_total = upload_total; + stats.upload_now = upload_now; + stats.currentFilename = out->currentFilename; + + MutexSafeWrapper safeMutex(out->ftpServer->getProgressMutex()); + out->ftpServer->getCallBackObject()->FTPClient_CallbackEvent(out->itemName, ftp_cct_DownloadProgress, ftp_crt_SUCCESS, &stats); + } + + return 0; +} + FTPClientThread::FTPClientThread(int portNumber, string serverUrl, std::pair mapsPath, std::pair tilesetsPath, FTPClientCallbackInterface *pCBObject) : BaseThread() { this->portNumber = portNumber; this->serverUrl = serverUrl; @@ -171,6 +200,7 @@ FTP_Client_ResultType FTPClientThread::getMapFromServer(string mapFileName, stri if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread about to try to RETR into [%s]\n",destFile.c_str()); struct FtpFile ftpfile = { + NULL, destFile.c_str(), /* name to store the file as if succesful */ NULL, NULL, @@ -233,7 +263,7 @@ void FTPClientThread::getMapFromServer(string mapFileName) { } if(this->pCBObject != NULL) { - this->pCBObject->FTPClient_CallbackEvent(mapFileName,ftp_cct_Map,result); + this->pCBObject->FTPClient_CallbackEvent(mapFileName,ftp_cct_Map,result,NULL); } } @@ -258,7 +288,7 @@ void FTPClientThread::getTilesetFromServer(string tileSetName) { } if(this->pCBObject != NULL) { - this->pCBObject->FTPClient_CallbackEvent(tileSetName,ftp_cct_Tileset,result); + this->pCBObject->FTPClient_CallbackEvent(tileSetName,ftp_cct_Tileset,result,NULL); } } @@ -301,6 +331,7 @@ FTP_Client_ResultType FTPClientThread::getTilesetFromServer(string tileSetName, if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread about to try to RETR into [%s]\n",destFile.c_str()); struct FtpFile ftpfile = { + tileSetName.c_str(), destFile.c_str(), // name to store the file as if succesful destFile.c_str(), NULL, @@ -328,13 +359,9 @@ FTP_Client_ResultType FTPClientThread::getTilesetFromServer(string tileSetName, // callback is called before download of concrete file started curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, file_is_comming); - // callback is called after data from the file have been transferred curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded); - // put transfer data into callbacks - // helper data - //struct callback_data data = { 0 }; curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &ftpfile); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); @@ -343,6 +370,10 @@ FTP_Client_ResultType FTPClientThread::getTilesetFromServer(string tileSetName, // Set a pointer to our struct to pass to the callback curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, file_progress); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &ftpfile); + // Switch on full protocol/debug output if(SystemFlags::VERBOSE_MODE_ENABLED) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);