diff options
| author | JMC47 <JMC4789@gmail.com> | 2020-09-23 12:27:43 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-23 12:27:43 -0400 |
| commit | 54e570a95f2cb54fdc7be29d04870746c69a8b9e (patch) | |
| tree | 1db68bbdaa591d6cd8025493478fa5d0dadf7980 /Source/Core | |
| parent | f33767f19cca6ee95af9727f0050f27e2571f770 (diff) | |
| parent | 5ba083215852a7f1afa2ac73316c2c0c500a6e7d (diff) | |
Merge pull request #8902 from JosJuice/android-convert
Android: Add disc image conversion
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Common/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | Source/Core/Common/File.cpp | 23 | ||||
| -rw-r--r-- | Source/Core/Common/FileUtil.cpp | 18 | ||||
| -rw-r--r-- | Source/Core/DiscIO/Blob.h | 12 | ||||
| -rw-r--r-- | Source/Core/DiscIO/CompressedBlob.cpp | 12 | ||||
| -rw-r--r-- | Source/Core/DiscIO/FileBlob.cpp | 4 | ||||
| -rw-r--r-- | Source/Core/DiscIO/WIABlob.cpp | 19 | ||||
| -rw-r--r-- | Source/Core/DiscIO/WIABlob.h | 6 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/ConvertDialog.cpp | 36 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/GameList/GameList.cpp | 7 | ||||
| -rw-r--r-- | Source/Core/UICommon/GameFile.cpp | 5 | ||||
| -rw-r--r-- | Source/Core/UICommon/GameFile.h | 1 |
12 files changed, 91 insertions, 57 deletions
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index a805635af6..9592043954 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -164,6 +164,11 @@ elseif(WIN32) if (_M_X86_64) target_link_libraries(common PRIVATE opengl32.lib) endif() +elseif (ANDROID) + target_link_libraries(common + PRIVATE + androidcommon + ) endif() if(ANDROID) diff --git a/Source/Core/Common/File.cpp b/Source/Core/Common/File.cpp index 9dfcdbd7d8..a724cbb723 100644 --- a/Source/Core/Common/File.cpp +++ b/Source/Core/Common/File.cpp @@ -15,6 +15,13 @@ #include <unistd.h> #endif +#ifdef ANDROID +#include <algorithm> + +#include "Common/StringUtil.h" +#include "jni/AndroidCommon/AndroidCommon.h" +#endif + #include "Common/CommonTypes.h" #include "Common/File.h" #include "Common/FileUtil.h" @@ -62,7 +69,21 @@ bool IOFile::Open(const std::string& filename, const char openmode[]) #ifdef _WIN32 m_good = _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str()) == 0; #else - m_file = std::fopen(filename.c_str(), openmode); +#ifdef ANDROID + if (StringBeginsWith(filename, "content://")) + { + // The Java method which OpenAndroidContent passes the mode to does not support the b specifier. + // Since we're on POSIX, it's fine to just remove the b. + std::string mode_without_b(openmode); + mode_without_b.erase(std::remove(mode_without_b.begin(), mode_without_b.end(), 'b'), + mode_without_b.end()); + m_file = fdopen(OpenAndroidContent(filename, mode_without_b), mode_without_b.c_str()); + } + else +#endif + { + m_file = std::fopen(filename.c_str(), openmode); + } m_good = m_file != nullptr; #endif diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp index b3efa6b868..3c524ed9d8 100644 --- a/Source/Core/Common/FileUtil.cpp +++ b/Source/Core/Common/FileUtil.cpp @@ -46,6 +46,11 @@ #include <sys/param.h> #endif +#ifdef ANDROID +#include "Common/StringUtil.h" +#include "jni/AndroidCommon/AndroidCommon.h" +#endif + #ifndef S_ISDIR #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) #endif @@ -132,10 +137,19 @@ bool Delete(const std::string& filename) { INFO_LOG(COMMON, "Delete: file %s", filename.c_str()); +#ifdef ANDROID + if (StringBeginsWith(filename, "content://")) + { + const bool success = DeleteAndroidContent(filename); + if (!success) + WARN_LOG(COMMON, "Delete failed on %s", filename.c_str()); + return success; + } +#endif + const FileInfo file_info(filename); - // Return true because we care about the file no - // being there, not the actual delete. + // Return true because we care about the file not being there, not the actual delete. if (!file_info.Exists()) { WARN_LOG(COMMON, "Delete: %s does not exist", filename.c_str()); diff --git a/Source/Core/DiscIO/Blob.h b/Source/Core/DiscIO/Blob.h index 473aa9bfce..2166d8c677 100644 --- a/Source/Core/DiscIO/Blob.h +++ b/Source/Core/DiscIO/Blob.h @@ -15,6 +15,7 @@ // automatically do the right thing. #include <array> +#include <functional> #include <memory> #include <optional> #include <string> @@ -175,17 +176,16 @@ private: // Factory function - examines the path to choose the right type of BlobReader, and returns one. std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename); -typedef bool (*CompressCB)(const std::string& text, float percent, void* arg); +using CompressCB = std::function<bool(const std::string& text, float percent)>; bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path, - const std::string& outfile_path, u32 sub_type, int sector_size = 16384, - CompressCB callback = nullptr, void* arg = nullptr); + const std::string& outfile_path, u32 sub_type, int sector_size, + CompressCB callback); bool ConvertToPlain(BlobReader* infile, const std::string& infile_path, - const std::string& outfile_path, CompressCB callback = nullptr, - void* arg = nullptr); + const std::string& outfile_path, CompressCB callback); bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path, const std::string& outfile_path, bool rvz, WIARVZCompressionType compression_type, int compression_level, - int chunk_size, CompressCB callback = nullptr, void* arg = nullptr); + int chunk_size, CompressCB callback); } // namespace DiscIO diff --git a/Source/Core/DiscIO/CompressedBlob.cpp b/Source/Core/DiscIO/CompressedBlob.cpp index fdfd65baf8..4486b54827 100644 --- a/Source/Core/DiscIO/CompressedBlob.cpp +++ b/Source/Core/DiscIO/CompressedBlob.cpp @@ -238,7 +238,7 @@ static ConversionResult<OutputParameters> Compress(CompressThreadState* state, static ConversionResultCode Output(OutputParameters parameters, File::IOFile* outfile, u64* position, std::vector<u64>* offsets, int progress_monitor, - u32 num_blocks, CompressCB callback, void* arg) + u32 num_blocks, CompressCB callback) { u64 offset = *position; if (!parameters.compressed) @@ -261,7 +261,7 @@ static ConversionResultCode Output(OutputParameters parameters, File::IOFile* ou const float completion = static_cast<float>(parameters.block_number) / num_blocks; - if (!callback(text, completion, arg)) + if (!callback(text, completion)) return ConversionResultCode::Canceled; } @@ -270,7 +270,7 @@ static ConversionResultCode Output(OutputParameters parameters, File::IOFile* ou bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path, const std::string& outfile_path, u32 sub_type, int block_size, - CompressCB callback, void* arg) + CompressCB callback) { ASSERT(infile->IsDataSizeAccurate()); @@ -284,7 +284,7 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path, return false; } - callback(Common::GetStringT("Files opened, ready to compress."), 0, arg); + callback(Common::GetStringT("Files opened, ready to compress."), 0); CompressedBlobHeader header; header.magic_cookie = GCZ_MAGIC; @@ -317,7 +317,7 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path, const auto output = [&](OutputParameters parameters) { return Output(std::move(parameters), &outfile, &position, &offsets, progress_monitor, - header.num_blocks, callback, arg); + header.num_blocks, callback); }; MultithreadedCompressor<CompressThreadState, CompressParameters, OutputParameters> compressor( @@ -364,7 +364,7 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path, outfile.WriteArray(offsets.data(), header.num_blocks); outfile.WriteArray(hashes.data(), header.num_blocks); - callback(Common::GetStringT("Done compressing disc image."), 1.0f, arg); + callback(Common::GetStringT("Done compressing disc image."), 1.0f); } if (result == ConversionResultCode::ReadFailed) diff --git a/Source/Core/DiscIO/FileBlob.cpp b/Source/Core/DiscIO/FileBlob.cpp index ca0aa2cfd0..980b158dc9 100644 --- a/Source/Core/DiscIO/FileBlob.cpp +++ b/Source/Core/DiscIO/FileBlob.cpp @@ -42,7 +42,7 @@ bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr) } bool ConvertToPlain(BlobReader* infile, const std::string& infile_path, - const std::string& outfile_path, CompressCB callback, void* arg) + const std::string& outfile_path, CompressCB callback) { ASSERT(infile->IsDataSizeAccurate()); @@ -78,7 +78,7 @@ bool ConvertToPlain(BlobReader* infile, const std::string& infile_path, if (i % progress_monitor == 0) { const bool was_cancelled = - !callback(Common::GetStringT("Unpacking"), (float)i / (float)num_buffers, arg); + !callback(Common::GetStringT("Unpacking"), (float)i / (float)num_buffers); if (was_cancelled) { success = false; diff --git a/Source/Core/DiscIO/WIABlob.cpp b/Source/Core/DiscIO/WIABlob.cpp index 51a9c65694..4d4b104242 100644 --- a/Source/Core/DiscIO/WIABlob.cpp +++ b/Source/Core/DiscIO/WIABlob.cpp @@ -1686,9 +1686,9 @@ ConversionResultCode WIARVZFileReader<RVZ>::Output(std::vector<OutputParametersE } template <bool RVZ> -ConversionResultCode -WIARVZFileReader<RVZ>::RunCallback(size_t groups_written, u64 bytes_read, u64 bytes_written, - u32 total_groups, u64 iso_size, CompressCB callback, void* arg) +ConversionResultCode WIARVZFileReader<RVZ>::RunCallback(size_t groups_written, u64 bytes_read, + u64 bytes_written, u32 total_groups, + u64 iso_size, CompressCB callback) { int ratio = 0; if (bytes_read != 0) @@ -1700,8 +1700,8 @@ WIARVZFileReader<RVZ>::RunCallback(size_t groups_written, u64 bytes_read, u64 by const float completion = static_cast<float>(bytes_read) / iso_size; - return callback(text, completion, arg) ? ConversionResultCode::Success : - ConversionResultCode::Canceled; + return callback(text, completion) ? ConversionResultCode::Success : + ConversionResultCode::Canceled; } template <bool RVZ> @@ -1729,8 +1729,7 @@ template <bool RVZ> ConversionResultCode WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volume, File::IOFile* outfile, WIARVZCompressionType compression_type, - int compression_level, int chunk_size, CompressCB callback, - void* arg) + int compression_level, int chunk_size, CompressCB callback) { ASSERT(infile->IsDataSizeAccurate()); ASSERT(chunk_size > 0); @@ -1832,7 +1831,7 @@ WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volu return result; return RunCallback(parameters.group_index + parameters.entries.size(), parameters.bytes_read, - bytes_written, total_groups, iso_size, callback, arg); + bytes_written, total_groups, iso_size, callback); }; MultithreadedCompressor<CompressThreadState, CompressParameters, OutputParameters> mt_compressor( @@ -2030,7 +2029,7 @@ WIARVZFileReader<RVZ>::Convert(BlobReader* infile, const VolumeDisc* infile_volu bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path, const std::string& outfile_path, bool rvz, WIARVZCompressionType compression_type, int compression_level, - int chunk_size, CompressCB callback, void* arg) + int chunk_size, CompressCB callback) { File::IOFile outfile(outfile_path, "wb"); if (!outfile) @@ -2047,7 +2046,7 @@ bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path, const auto convert = rvz ? RVZFileReader::Convert : WIAFileReader::Convert; const ConversionResultCode result = convert(infile, infile_volume.get(), &outfile, compression_type, compression_level, - chunk_size, callback, arg); + chunk_size, callback); if (result == ConversionResultCode::ReadFailed) PanicAlertT("Failed to read from the input file \"%s\".", infile_path.c_str()); diff --git a/Source/Core/DiscIO/WIABlob.h b/Source/Core/DiscIO/WIABlob.h index c76af169f2..5b08dd227c 100644 --- a/Source/Core/DiscIO/WIABlob.h +++ b/Source/Core/DiscIO/WIABlob.h @@ -64,8 +64,7 @@ public: static ConversionResultCode Convert(BlobReader* infile, const VolumeDisc* infile_volume, File::IOFile* outfile, WIARVZCompressionType compression_type, - int compression_level, int chunk_size, CompressCB callback, - void* arg); + int compression_level, int chunk_size, CompressCB callback); private: using SHA1 = std::array<u8, 20>; @@ -351,8 +350,7 @@ private: std::mutex* reusable_groups_mutex, GroupEntry* group_entry, u64* bytes_written); static ConversionResultCode RunCallback(size_t groups_written, u64 bytes_read, u64 bytes_written, - u32 total_groups, u64 iso_size, CompressCB callback, - void* arg); + u32 total_groups, u64 iso_size, CompressCB callback); bool m_valid; WIARVZCompressionType m_compression_type; diff --git a/Source/Core/DolphinQt/ConvertDialog.cpp b/Source/Core/DolphinQt/ConvertDialog.cpp index 5a41ccea36..a14e728c40 100644 --- a/Source/Core/DolphinQt/ConvertDialog.cpp +++ b/Source/Core/DolphinQt/ConvertDialog.cpp @@ -32,17 +32,6 @@ #include "UICommon/GameFile.h" #include "UICommon/UICommon.h" -static bool CompressCB(const std::string& text, float percent, void* ptr) -{ - if (ptr == nullptr) - return false; - - auto* progress_dialog = static_cast<ParallelProgressDialog*>(ptr); - - progress_dialog->SetValue(percent * 100); - return !progress_dialog->WasCanceled(); -} - ConvertDialog::ConvertDialog(QList<std::shared_ptr<const UICommon::GameFile>> files, QWidget* parent) : QDialog(parent), m_files(std::move(files)) @@ -463,15 +452,19 @@ void ConvertDialog::Convert() } else { + const auto callback = [&progress_dialog](const std::string& text, float percent) { + progress_dialog.SetValue(percent * 100); + return !progress_dialog.WasCanceled(); + }; + std::future<bool> success; switch (format) { case DiscIO::BlobType::PLAIN: success = std::async(std::launch::async, [&] { - const bool good = - DiscIO::ConvertToPlain(blob_reader.get(), original_path, dst_path.toStdString(), - &CompressCB, &progress_dialog); + const bool good = DiscIO::ConvertToPlain(blob_reader.get(), original_path, + dst_path.toStdString(), callback); progress_dialog.Reset(); return good; }); @@ -479,10 +472,9 @@ void ConvertDialog::Convert() case DiscIO::BlobType::GCZ: success = std::async(std::launch::async, [&] { - const bool good = - DiscIO::ConvertToGCZ(blob_reader.get(), original_path, dst_path.toStdString(), - file->GetPlatform() == DiscIO::Platform::WiiDisc ? 1 : 0, - block_size, &CompressCB, &progress_dialog); + const bool good = DiscIO::ConvertToGCZ( + blob_reader.get(), original_path, dst_path.toStdString(), + file->GetPlatform() == DiscIO::Platform::WiiDisc ? 1 : 0, block_size, callback); progress_dialog.Reset(); return good; }); @@ -491,10 +483,10 @@ void ConvertDialog::Convert() case DiscIO::BlobType::WIA: case DiscIO::BlobType::RVZ: success = std::async(std::launch::async, [&] { - const bool good = DiscIO::ConvertToWIAOrRVZ( - blob_reader.get(), original_path, dst_path.toStdString(), - format == DiscIO::BlobType::RVZ, compression, compression_level, block_size, - &CompressCB, &progress_dialog); + const bool good = + DiscIO::ConvertToWIAOrRVZ(blob_reader.get(), original_path, dst_path.toStdString(), + format == DiscIO::BlobType::RVZ, compression, + compression_level, block_size, callback); progress_dialog.Reset(); return good; }); diff --git a/Source/Core/DolphinQt/GameList/GameList.cpp b/Source/Core/DolphinQt/GameList/GameList.cpp index 956bc704dc..11cbadb2d3 100644 --- a/Source/Core/DolphinQt/GameList/GameList.cpp +++ b/Source/Core/DolphinQt/GameList/GameList.cpp @@ -267,9 +267,8 @@ void GameList::ShowContextMenu(const QPoint&) { const auto selected_games = GetSelectedGames(); - if (std::all_of(selected_games.begin(), selected_games.end(), [](const auto& game) { - return DiscIO::IsDisc(game->GetPlatform()) && game->IsVolumeSizeAccurate(); - })) + if (std::all_of(selected_games.begin(), selected_games.end(), + [](const auto& game) { return game->ShouldAllowConversion(); })) { menu->addAction(tr("Convert Selected Files..."), this, &GameList::ConvertFile); menu->addSeparator(); @@ -301,7 +300,7 @@ void GameList::ShowContextMenu(const QPoint&) { menu->addAction(tr("Set as &Default ISO"), this, &GameList::SetDefaultISO); - if (game->IsVolumeSizeAccurate()) + if (game->ShouldAllowConversion()) menu->addAction(tr("Convert File..."), this, &GameList::ConvertFile); QAction* change_disc = menu->addAction(tr("Change &Disc"), this, &GameList::ChangeDisc); diff --git a/Source/Core/UICommon/GameFile.cpp b/Source/Core/UICommon/GameFile.cpp index 30641d58e5..ff0fa84798 100644 --- a/Source/Core/UICommon/GameFile.cpp +++ b/Source/Core/UICommon/GameFile.cpp @@ -672,6 +672,11 @@ std::string GameFile::GetFileFormatName() const } } +bool GameFile::ShouldAllowConversion() const +{ + return DiscIO::IsDisc(m_platform) && m_volume_size_is_accurate; +} + const GameBanner& GameFile::GetBannerImage() const { return m_custom_banner.empty() ? m_volume_banner : m_custom_banner; diff --git a/Source/Core/UICommon/GameFile.h b/Source/Core/UICommon/GameFile.h index 9366b33f2e..3aa693507f 100644 --- a/Source/Core/UICommon/GameFile.h +++ b/Source/Core/UICommon/GameFile.h @@ -101,6 +101,7 @@ public: const std::string& GetCompressionMethod() const { return m_compression_method; } bool ShouldShowFileFormatDetails() const; std::string GetFileFormatName() const; + bool ShouldAllowConversion() const; const std::string& GetApploaderDate() const { return m_apploader_date; } u64 GetFileSize() const { return m_file_size; } u64 GetVolumeSize() const { return m_volume_size; } |
