From d234fa24e65a69cb1fc3f5b6b11a11ba844be507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 8 Dec 2023 14:05:12 +0100 Subject: [PATCH] Add progress bar (without %) to install/uninstall. Other fixes. --- Common/File/AndroidStorage.cpp | 5 +-- Core/Util/GameDB.cpp | 8 +++-- Core/Util/GameManager.cpp | 65 ++++++++++++++++++++++------------ Core/Util/GameManager.h | 3 +- UI/Store.cpp | 8 ++++- 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/Common/File/AndroidStorage.cpp b/Common/File/AndroidStorage.cpp index efb8a3360ac7..17e973ddb831 100644 --- a/Common/File/AndroidStorage.cpp +++ b/Common/File/AndroidStorage.cpp @@ -245,8 +245,9 @@ std::vector Android_ListContentUri(const std::string &path, bool env->DeleteLocalRef(fileList); double elapsed = time_now_d() - start; - if (elapsed > 0.1) { - INFO_LOG(FILESYS, "Listing directory on content URI took %0.3f s (%d files)", elapsed, (int)items.size()); + double threshold = 0.1; + if (elapsed >= threshold) { + INFO_LOG(FILESYS, "Listing directory on content URI '%s' took %0.3f s (%d files, log threshold = %0.3f)", path.c_str(), elapsed, (int)items.size(), threshold); } return items; } diff --git a/Core/Util/GameDB.cpp b/Core/Util/GameDB.cpp index 97fc02b0c72f..8e688e34aa38 100644 --- a/Core/Util/GameDB.cpp +++ b/Core/Util/GameDB.cpp @@ -128,8 +128,12 @@ bool GameDB::GetGameInfos(std::string_view id, std::vector *infos) { // Ignore version and stuff for now if (IDMatches(id, serial)) { GameDBInfo info; - sscanf(line.crc.data(), "%08x", &info.crc); - sscanf(line.size.data(), "%llu", &info.size); + if (1 != sscanf(line.crc.data(), "%08x", &info.crc)) { + continue; + } + if (1 != sscanf(line.size.data(), "%llu", (long long *)&info.size)) { + continue; + } info.title = line.title; info.foreignTitle = line.foreignTitle; infos->push_back(info); diff --git a/Core/Util/GameManager.cpp b/Core/Util/GameManager.cpp index cca6134e0d04..52bc6a6821fc 100644 --- a/Core/Util/GameManager.cpp +++ b/Core/Util/GameManager.cpp @@ -36,6 +36,7 @@ #include "Common/Data/Encoding/Utf8.h" #include "Common/Data/Format/IniFile.h" #include "Common/Log.h" +#include "Common/System/OSD.h" #include "Common/File/FileUtil.h" #include "Common/StringUtils.h" #include "Common/Thread/ThreadUtil.h" @@ -127,24 +128,32 @@ float GameManager::DownloadSpeedKBps() { return 0.0f; } -bool GameManager::UninstallGame(std::string name) { +void GameManager::UninstallGame(std::string name) { + SetCurrentThreadName("UninstallGame"); + + AndroidJNIThreadContext context; // Destructor detaches. + Path gameDir = GetSysDirectory(DIRECTORY_GAME) / name; + + auto st = GetI18NCategory(I18NCat::STORE); + INFO_LOG(HLE, "Uninstalling '%s'", gameDir.c_str()); if (!File::Exists(gameDir)) { ERROR_LOG(HLE, "Game '%s' not installed, cannot uninstall", name.c_str()); - return false; + return; } - + g_OSD.SetProgressBar("install", st->T("Uninstall"), 0.0f, 0.0f, 0.0f, 0.1f); bool success = File::DeleteDirRecursively(gameDir); + g_OSD.RemoveProgressBar("install", success, 0.5f); if (success) { INFO_LOG(HLE, "Successfully uninstalled game '%s'", name.c_str()); InstallDone(); cleanRecentsAfter_ = true; - return true; + return; } else { ERROR_LOG(HLE, "Failed to uninstalled game '%s'", name.c_str()); InstallDone(); - return false; + return; } } @@ -285,58 +294,69 @@ bool GameManager::InstallGame(Path url, Path fileName, bool deleteAfter) { } AndroidJNIThreadContext context; // Destructor detaches. - if (!File::Exists(fileName)) { ERROR_LOG(HLE, "Game file '%s' doesn't exist", fileName.c_str()); return false; } + auto st = GetI18NCategory(I18NCat::STORE); + auto di = GetI18NCategory(I18NCat::DIALOG); + auto sy = GetI18NCategory(I18NCat::SYSTEM); + + g_OSD.SetProgressBar("install", di->T("Installing..."), 0.0f, 0.0f, 0.0f, 0.1f); + std::string extension = url.GetFileExtension(); // Examine the URL to guess out what we're installing. if (extension == ".cso" || extension == ".iso") { // It's a raw ISO or CSO file. We just copy it to the destination. std::string shortFilename = url.GetFilename(); - return InstallRawISO(fileName, shortFilename, deleteAfter); + bool success = InstallRawISO(fileName, shortFilename, deleteAfter); + g_OSD.RemoveProgressBar("install", success, 0.5f); + return success; } - auto sy = GetI18NCategory(I18NCat::SYSTEM); - Path pspGame = GetSysDirectory(DIRECTORY_GAME); Path dest = pspGame; int error = 0; struct zip *z = ZipOpenPath(fileName); if (!z) { + g_OSD.RemoveProgressBar("install", false, 0.5f); SetInstallError(sy->T("Unable to open zip file")); return false; } ZipFileInfo info; ZipFileContents contents = DetectZipFileContents(z, &info); + bool success = false; switch (contents) { case ZipFileContents::PSP_GAME_DIR: INFO_LOG(HLE, "Installing '%s' into '%s'", fileName.c_str(), pspGame.c_str()); - // InstallMemstickGame contains code to close z. - return InstallMemstickGame(z, fileName, pspGame, info, false, deleteAfter); + // InstallMemstickGame contains code to close (and delete) z. + success = InstallMemstickGame(z, fileName, pspGame, info, false, deleteAfter); + break; case ZipFileContents::ISO_FILE: INFO_LOG(HLE, "Installing '%s' into its containing directory", fileName.c_str()); // InstallZippedISO contains code to close z. - return InstallZippedISO(z, info.isoFileIndex, fileName, deleteAfter); + success = InstallZippedISO(z, info.isoFileIndex, fileName, deleteAfter); + break; case ZipFileContents::TEXTURE_PACK: // InstallMemstickGame contains code to close z, and works for textures too. if (DetectTexturePackDest(z, info.textureIniIndex, dest)) { - INFO_LOG(HLE, "Installing '%s' into '%s'", fileName.c_str(), dest.c_str()); + INFO_LOG(HLE, "Installing texture pack '%s' into '%s'", fileName.c_str(), dest.c_str()); File::CreateFullPath(dest); - // Install as a zip file if textures.ini is in the root. Performs better on Android. - if (info.stripChars == 0) - return InstallMemstickZip(z, fileName, dest / "textures.zip", info, deleteAfter); - File::CreateEmptyFile(dest / ".nomedia"); - return InstallMemstickGame(z, fileName, dest, info, true, deleteAfter); + // Install as a zip file if textures.ini is in the root. Performs better on Android. + if (info.stripChars == 0) { + success = InstallMemstickZip(z, fileName, dest / "textures.zip", info, deleteAfter); + } else { + File::CreateEmptyFile(dest / ".nomedia"); + success = InstallMemstickGame(z, fileName, dest, info, true, deleteAfter); + } } else { zip_close(z); z = nullptr; } - return false; + break; default: ERROR_LOG(HLE, "File not a PSP game, no EBOOT.PBP found."); SetInstallError(sy->T("Not a PSP game")); @@ -344,8 +364,10 @@ bool GameManager::InstallGame(Path url, Path fileName, bool deleteAfter) { z = nullptr; if (deleteAfter) File::Delete(fileName); - return false; + break; } + g_OSD.RemoveProgressBar("install", success, 0.5f); + return success; } bool GameManager::DetectTexturePackDest(struct zip *z, int iniIndex, Path &dest) { @@ -598,11 +620,11 @@ bool GameManager::InstallMemstickGame(struct zip *z, const Path &zipfile, const } } INFO_LOG(HLE, "Extracted %d files from zip (%d bytes / %d).", info.numFiles, (int)bytesCopied, (int)allBytes); - zip_close(z); z = nullptr; installProgress_ = 1.0f; if (deleteAfter) { + INFO_LOG(HLE, "Deleting '%s' after extraction", zipfile.c_str()); File::Delete(zipfile); } InstallDone(); @@ -679,7 +701,6 @@ bool GameManager::InstallMemstickZip(struct zip *z, const Path &zipfile, const P bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, const Path &zipfile, bool deleteAfter) { // Let's place the output file in the currently selected Games directory. - std::string fn = zip_get_name(z, isoFileIndex, 0); size_t nameOffset = fn.rfind('/'); if (nameOffset == std::string::npos) { diff --git a/Core/Util/GameManager.h b/Core/Util/GameManager.h index 66544669c252..0d6b9ce78e64 100644 --- a/Core/Util/GameManager.h +++ b/Core/Util/GameManager.h @@ -78,12 +78,13 @@ class GameManager { bool UninstallGameOnThread(const std::string &name); private: + // TODO: The return value on this is a bit pointless, we can't get at it. bool InstallGame(Path url, Path tempFileName, bool deleteAfter); bool InstallMemstickGame(struct zip *z, const Path &zipFile, const Path &dest, const ZipFileInfo &info, bool allowRoot, bool deleteAfter); bool InstallMemstickZip(struct zip *z, const Path &zipFile, const Path &dest, const ZipFileInfo &info, bool deleteAfter); bool InstallZippedISO(struct zip *z, int isoFileIndex, const Path &zipfile, bool deleteAfter); bool InstallRawISO(const Path &zipFile, const std::string &originalName, bool deleteAfter); - bool UninstallGame(std::string name); + void UninstallGame(std::string name); void InstallDone(); diff --git a/UI/Store.cpp b/UI/Store.cpp index aaca7efbe44e..baacc3de9a7a 100644 --- a/UI/Store.cpp +++ b/UI/Store.cpp @@ -274,6 +274,7 @@ class ProductView : public UI::LinearLayout { std::string DownloadURL(); StoreEntry entry_; + UI::Button *uninstallButton_ = nullptr; UI::Button *installButton_ = nullptr; UI::Button *launchButton_ = nullptr; UI::Button *cancelButton_ = nullptr; @@ -300,6 +301,7 @@ void ProductView::CreateViews() { LinearLayout *progressDisplay = new LinearLayout(ORIENT_HORIZONTAL); installButton_ = progressDisplay->Add(new Button(st->T("Install"))); installButton_->OnClick.Handle(this, &ProductView::OnInstall); + uninstallButton_ = nullptr; speedView_ = progressDisplay->Add(new TextView("")); speedView_->SetVisibility(isDownloading ? V_VISIBLE : V_GONE); @@ -308,7 +310,8 @@ void ProductView::CreateViews() { installButton_ = nullptr; speedView_ = nullptr; Add(new TextView(st->T("Already Installed"))); - Add(new Button(st->T("Uninstall")))->OnClick.Add([=](UI::EventParams &e) { + uninstallButton_ = new Button(st->T("Uninstall")); + Add(uninstallButton_)->OnClick.Add([=](UI::EventParams &e) { g_GameManager.UninstallGameOnThread(entry_.file); return UI::EVENT_DONE; }); @@ -341,6 +344,9 @@ void ProductView::Update() { if (installButton_) { installButton_->SetEnabled(g_GameManager.GetState() == GameManagerState::IDLE); } + if (uninstallButton_) { + uninstallButton_->SetEnabled(g_GameManager.GetState() == GameManagerState::IDLE); + } if (g_GameManager.GetState() == GameManagerState::DOWNLOADING) { if (speedView_) { float speed = g_GameManager.DownloadSpeedKBps();