diff --git a/src/addons/addons_manager.cpp b/src/addons/addons_manager.cpp index 58885cc35..653463516 100644 --- a/src/addons/addons_manager.cpp +++ b/src/addons/addons_manager.cpp @@ -104,7 +104,7 @@ void AddonsManager::initOnline(const XMLNode *xml) if(file_manager->fileExists(full_path)) { if(UserConfigParams::m_verbosity>=3) - printf("Removing cached icon '%s'.\n", + printf("[addons] Removing cached icon '%s'.\n", addon.getIconBasename().c_str()); file_manager->removeFile(full_path); } @@ -124,9 +124,9 @@ void AddonsManager::initOnline(const XMLNode *xml) else { fprintf(stderr, - "Found invalid node '%s' while downloading addons.\n", + "[addons] Found invalid node '%s' while downloading addons.\n", node->getName().c_str()); - fprintf(stderr, "Ignored.\n"); + fprintf(stderr, "[addons] Ignored.\n"); } } // for igetNumNodes delete xml; @@ -205,7 +205,7 @@ void *AddonsManager::downloadIcons(void *obj) for(unsigned int i=0; im_addons_list.getData().size(); i++) { if(!me->m_addons_list.getData()[i].iconReady()) - printf("No icon for '%s'.\n", + printf("[addons] No icon for '%s'.\n", me->m_addons_list.getData()[i].getId().c_str()); } me->saveInstalled(); @@ -230,7 +230,7 @@ bool AddonsManager::onlineReady() void AddonsManager::loadInstalledAddons() { /* checking for installed addons */ - std::cout << "[Addons] Loading an xml file for installed addons: "; + std::cout << "[addons] Loading an xml file for installed addons: "; std::cout << m_file_installed << std::endl; const XMLNode *xml = file_manager->createXMLTree(m_file_installed); if(!xml) diff --git a/src/addons/network_http.cpp b/src/addons/network_http.cpp index bb103e3de..c5b525f0a 100644 --- a/src/addons/network_http.cpp +++ b/src/addons/network_http.cpp @@ -54,7 +54,7 @@ NetworkHttp *network_http; * This separate thread is running in NetworkHttp::mainLoop, and is being * waken up if a command is issued (e.g. using downloadFileAsynchronous). */ -NetworkHttp::NetworkHttp() : m_news(""), m_progress(-1.0f) +NetworkHttp::NetworkHttp() : m_news(""), m_progress(-1.0f), m_abort(false) { pthread_mutex_init(&m_mutex_command, NULL); pthread_cond_init(&m_cond_command, NULL); @@ -133,15 +133,24 @@ void *NetworkHttp::mainLoop(void *obj) */ NetworkHttp::~NetworkHttp() { + // if a download should be active (which means it was cancelled by the + // user, in which case it will still be ongoing in the background) + // we can't get the mutex, and would have to wait for a timeout, + // and we couldn't finish STK. This way we request an abort of + // a download, which mean we can get the mutex and ask the service + // thread here to cancel properly. + cancelDownload(); pthread_mutex_lock(&m_mutex_command); { m_command=HC_QUIT; pthread_cond_signal(&m_cond_command); } pthread_mutex_unlock(&m_mutex_command); + printf("[addons] Mutex unlocked.\n"); void *result; pthread_join(m_thread_id, &result); + printf("[addons] Network thread joined.\n"); pthread_mutex_destroy(&m_mutex_command); pthread_cond_destroy(&m_cond_command); @@ -213,6 +222,7 @@ size_t NetworkHttp::writeStr(char ptr [], size_t size, size_t nb_char, std::string NetworkHttp::downloadToStrInternal(std::string url) { + m_abort.set(false); CURL *session = curl_easy_init(); std::string full_url = (std::string)UserConfigParams::m_server_addons @@ -244,7 +254,7 @@ bool NetworkHttp::downloadFileInternal(const std::string &file, bool is_asynchron) { if(UserConfigParams::m_verbosity>=3) - printf("Downloading %s\n", file.c_str()); + printf("[addons] Downloading %s\n", file.c_str()); CURL *session = curl_easy_init(); std::string full_url = (std::string)UserConfigParams::m_server_addons + "/" + file; @@ -277,6 +287,18 @@ bool NetworkHttp::downloadFileInternal(const std::string &file, return success==CURLE_OK; } // downloadFileInternal +// ---------------------------------------------------------------------------- +/** Signals to the progress function to request any ongoing download to be + * cancelled. This function can also be called if there is actually no + * download atm. The function progressDownload checks m_abort and will + * return a non-zero value which causes libcurl to abort. */ +void NetworkHttp::cancelDownload() +{ + if(UserConfigParams::m_verbosity>=3) + printf("[addons] Requesting cancellation of download.\n"); + m_abort.set(true); +} // cancelDownload + // ---------------------------------------------------------------------------- /** External interface to download a file synchronously, i.e. it will only * return once the download is complete. @@ -288,6 +310,9 @@ bool NetworkHttp::downloadFileSynchron(const std::string &file, const std::string &save) { const std::string &save_filename = (save!="") ? save : file; + if(UserConfigParams::m_verbosity>=3) + printf("[addons] Download synchron '%s' as '%s'.\n", + file.c_str(), save_filename.c_str()); return downloadFileInternal(file, save_filename, /*is_asynchron*/false); @@ -308,6 +333,9 @@ void NetworkHttp::downloadFileAsynchron(const std::string &file, m_file = file; m_save_filename = (save!="") ? save : file; + if(UserConfigParams::m_verbosity>=3) + printf("[addons] Download asynchron '%s' as '%s'.\n", + file.c_str(), m_save_filename.c_str()); // Wake up the network http thread pthread_mutex_lock(&m_mutex_command); { @@ -329,6 +357,14 @@ int NetworkHttp::progressDownload(void *clientp, double download_total, double download_now, double upload_total, double upload_now) { + // Check if we are asked to abort the download. If so, signal this + // back to libcurl by returning a non-zero status. + if(network_http->m_abort.get()) + { + if(UserConfigParams::m_verbosity>=3) + printf("[addons] Aborting download in progress.\n"); + return 1; + } float f; if(download_now < download_total) { diff --git a/src/addons/network_http.hpp b/src/addons/network_http.hpp index 0183113ba..f455d4cfe 100644 --- a/src/addons/network_http.hpp +++ b/src/addons/network_http.hpp @@ -64,6 +64,9 @@ private: * this value only becomes 1.0f, if the download is completed.*/ Synchronised m_progress; + /** Signal an abort in case that a download is still happening. */ + Synchronised m_abort; + /** Thread id of the thread running in this object. */ pthread_t m_thread_id; @@ -91,7 +94,7 @@ public: const std::string getNewsMessage() const; float getProgress() const; - + void cancelDownload(); }; // NetworkHttp extern NetworkHttp *network_http; diff --git a/src/addons/zip.cpp b/src/addons/zip.cpp index 2b4a58fb5..16e01337c 100644 --- a/src/addons/zip.cpp +++ b/src/addons/zip.cpp @@ -75,7 +75,7 @@ bool extract_zip(const std::string &from, const std::string &to) for(unsigned int i=0; igetFileCount(); i++) { const std::string current_file=zip_file_list->getFileName(i).c_str(); - std::cout << current_file << std::endl; + printf("[addons] Unzipping file '%s'.\n", current_file.c_str()); if(zip_file_list->isDirectory(i)) continue; if(current_file[0]=='.') continue; const std::string base = StringUtils::getBasename(current_file); @@ -84,8 +84,8 @@ bool extract_zip(const std::string &from, const std::string &to) file_system->createAndOpenFile(current_file.c_str()); if(!src_file) { - printf("Can't read file '%s'.\n", current_file.c_str()); - printf("This is ignored, but the addon might not work.\n"); + printf("[addons] Can't read file '%s'.\n", current_file.c_str()); + printf("[addons] This is ignored, but the addon might not work.\n"); error = true; continue; } @@ -94,19 +94,19 @@ bool extract_zip(const std::string &from, const std::string &to) file_system->createAndWriteFile((to+"/"+base).c_str()); if(dst_file == NULL) { - printf("Couldn't create the file '%s'.\n", + printf("[addons] Couldn't create the file '%s'.\n", (to+"/"+current_file).c_str()); - printf("The directory might not exist.\n"); - printf("This is ignored, but the addon might not work.\n"); + printf("[addons] The directory might not exist.\n"); + printf("[addons] This is ignored, but the addon might not work.\n"); error = true; continue; } if (IFileSystem_copyFileToFile(dst_file, src_file) < 0) { - printf("Could not copy '%s' from archive '%s'.\n", + printf("[addons] Could not copy '%s' from archive '%s'.\n", current_file.c_str(), from.c_str()); - printf("This is ignored, but the addon might not work.\n"); + printf("[addons] This is ignored, but the addon might not work.\n"); error = true; } dst_file->drop(); diff --git a/src/states_screens/addons_screen.cpp b/src/states_screens/addons_screen.cpp index 048f62ae4..7e720e0a1 100644 --- a/src/states_screens/addons_screen.cpp +++ b/src/states_screens/addons_screen.cpp @@ -64,13 +64,11 @@ void AddonsScreen::init() Screen::init(); getWidget("category")->setDeactivated(); - std::cout << "[Addons] Using directory <" + file_manager->getAddonsDir() + std::cout << "[addons] Using directory <" + file_manager->getAddonsDir() << ">\n"; GUIEngine::ListWidget* w_list = getWidget("list_addons"); w_list->setIcons(m_icon_bank); - //w_list->clear(); - std::cout << "icon bank" << std::endl; getWidget("update_status") ->setText(_("Updating the list...")); diff --git a/src/states_screens/dialogs/addons_loading.cpp b/src/states_screens/dialogs/addons_loading.cpp index 7f879e2de..3c6d3ca6f 100644 --- a/src/states_screens/dialogs/addons_loading.cpp +++ b/src/states_screens/dialogs/addons_loading.cpp @@ -83,6 +83,7 @@ GUIEngine::EventPropagation { if(event_source == "cancel") { + network_http->cancelDownload(); dismiss(); return GUIEngine::EVENT_BLOCK; }