mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-21 18:39:57 +00:00
implement cellPhotoImport
This commit is contained in:
parent
3d73915358
commit
577f379a12
@ -1,11 +1,13 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
#include "Emu/Cell/lv2/sys_fs.h"
|
#include "Emu/Cell/lv2/sys_fs.h"
|
||||||
|
#include "Emu/RSX/Overlays/overlay_media_list_dialog.h"
|
||||||
|
#include "Emu/VFS.h"
|
||||||
|
#include "Emu/System.h"
|
||||||
|
#include "Utilities/StrUtil.h"
|
||||||
#include "cellSysutil.h"
|
#include "cellSysutil.h"
|
||||||
|
|
||||||
|
LOG_CHANNEL(cellPhotoImportUtil, "PhotoImport");
|
||||||
|
|
||||||
LOG_CHANNEL(cellPhotoImportUtil);
|
|
||||||
|
|
||||||
// Return Codes
|
// Return Codes
|
||||||
enum CellPhotoImportError : u32
|
enum CellPhotoImportError : u32
|
||||||
@ -37,6 +39,11 @@ void fmt_class_string<CellPhotoImportError>::format(std::string& out, u64 arg)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CellPhotoImportVersion : u32
|
||||||
|
{
|
||||||
|
CELL_PHOTO_IMPORT_VERSION_CURRENT = 0,
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CELL_PHOTO_IMPORT_HDD_PATH_MAX = 1055,
|
CELL_PHOTO_IMPORT_HDD_PATH_MAX = 1055,
|
||||||
@ -92,36 +99,199 @@ struct CellPhotoImportSetParam
|
|||||||
|
|
||||||
using CellPhotoImportFinishCallback = void(s32 result, vm::ptr<CellPhotoImportFileData> filedata, vm::ptr<void> userdata);
|
using CellPhotoImportFinishCallback = void(s32 result, vm::ptr<CellPhotoImportFileData> filedata, vm::ptr<void> userdata);
|
||||||
|
|
||||||
|
struct photo_import
|
||||||
|
{
|
||||||
|
shared_mutex mutex;
|
||||||
|
bool is_busy = false;
|
||||||
|
CellPhotoImportSetParam param{};
|
||||||
|
vm::ptr<CellPhotoImportFinishCallback> func_finish{};
|
||||||
|
vm::ptr<void> userdata{};
|
||||||
|
};
|
||||||
|
|
||||||
|
error_code select_photo(std::string dst_dir)
|
||||||
|
{
|
||||||
|
auto& pi_manager = g_fxo->get<photo_import>();
|
||||||
|
|
||||||
|
if (!pi_manager.func_finish)
|
||||||
|
return CELL_PHOTO_IMPORT_ERROR_PARAM;
|
||||||
|
|
||||||
|
if (!fs::is_dir(dst_dir))
|
||||||
|
{
|
||||||
|
// TODO: check if the dir is user accessible and can be written to
|
||||||
|
return CELL_PHOTO_IMPORT_ERROR_PARAM; // TODO: is this correct?
|
||||||
|
}
|
||||||
|
|
||||||
|
pi_manager.is_busy = true;
|
||||||
|
|
||||||
|
const std::string vfs_dir_path = vfs::get("/dev_hdd0/photo");
|
||||||
|
const std::string title = get_localized_string(localized_string_id::RSX_OVERLAYS_MEDIA_DIALOG_TITLE_PHOTO_IMPORT);
|
||||||
|
|
||||||
|
error_code error = rsx::overlays::show_media_list_dialog(rsx::overlays::media_list_dialog::media_type::photo, vfs_dir_path, title,
|
||||||
|
[&pi_manager, dst_dir](s32 status, utils::media_info info)
|
||||||
|
{
|
||||||
|
sysutil_register_cb([&pi_manager, dst_dir, info, status](ppu_thread& ppu) -> s32
|
||||||
|
{
|
||||||
|
vm::var<CellPhotoImportFileData> filedata = vm::make_var(CellPhotoImportFileData{});
|
||||||
|
vm::var<CellPhotoImportFileDataSub> sub = vm::make_var(CellPhotoImportFileDataSub{});
|
||||||
|
|
||||||
|
u32 result = status >= 0 ? u32{CELL_OK} : u32{CELL_CANCEL};
|
||||||
|
|
||||||
|
if (result == CELL_OK)
|
||||||
|
{
|
||||||
|
fs::stat_t f_info{};
|
||||||
|
|
||||||
|
if (!fs::stat(info.path, f_info) || f_info.is_directory)
|
||||||
|
{
|
||||||
|
result = CELL_PHOTO_IMPORT_ERROR_ACCESS_ERROR; // TODO: is this correct ?
|
||||||
|
pi_manager.func_finish(ppu, result, filedata, pi_manager.userdata);
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f_info.size > pi_manager.param.fileSizeMax)
|
||||||
|
{
|
||||||
|
result = CELL_PHOTO_IMPORT_ERROR_COPY; // TODO: is this correct ?
|
||||||
|
pi_manager.func_finish(ppu, result, filedata, pi_manager.userdata);
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string filename = info.path.substr(info.path.find_last_of(fs::delim) + 1);
|
||||||
|
const std::string title = info.get_metadata("title", filename);
|
||||||
|
const std::string sub_type = fmt::to_lower(info.sub_type);
|
||||||
|
const std::string dst_path = dst_dir + "/" + filename;
|
||||||
|
|
||||||
|
strcpy_trunc(filedata->dstFileName, filename);
|
||||||
|
strcpy_trunc(filedata->photo_title, title);
|
||||||
|
strcpy_trunc(filedata->game_title, Emu.GetTitle());
|
||||||
|
// strcpy_trunc(filedata->game_comment, ...); // TODO
|
||||||
|
|
||||||
|
filedata->data_sub = sub;
|
||||||
|
filedata->data_sub->width = info.width;
|
||||||
|
filedata->data_sub->height = info.height;
|
||||||
|
|
||||||
|
if (sub_type == "jpg" || sub_type == "jpeg")
|
||||||
|
{
|
||||||
|
filedata->data_sub->format = CELL_PHOTO_IMPORT_FT_JPEG;
|
||||||
|
}
|
||||||
|
else if (sub_type == "png")
|
||||||
|
{
|
||||||
|
filedata->data_sub->format = CELL_PHOTO_IMPORT_FT_PNG;
|
||||||
|
}
|
||||||
|
else if (sub_type == "tif" || sub_type == "tiff")
|
||||||
|
{
|
||||||
|
filedata->data_sub->format = CELL_PHOTO_IMPORT_FT_TIFF;
|
||||||
|
}
|
||||||
|
else if (sub_type == "bmp")
|
||||||
|
{
|
||||||
|
filedata->data_sub->format = CELL_PHOTO_IMPORT_FT_BMP;
|
||||||
|
}
|
||||||
|
else if (sub_type == "gif")
|
||||||
|
{
|
||||||
|
filedata->data_sub->format = CELL_PHOTO_IMPORT_FT_GIF;
|
||||||
|
}
|
||||||
|
else if (sub_type == "mpo")
|
||||||
|
{
|
||||||
|
filedata->data_sub->format = CELL_PHOTO_IMPORT_FT_MPO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filedata->data_sub->format = CELL_PHOTO_IMPORT_FT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (info.orientation)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case CELL_SEARCH_ORIENTATION_UNKNOWN:
|
||||||
|
case CELL_SEARCH_ORIENTATION_TOP_LEFT:
|
||||||
|
filedata->data_sub->rotate = CELL_PHOTO_IMPORT_TEX_ROT_0;
|
||||||
|
break;
|
||||||
|
case CELL_SEARCH_ORIENTATION_TOP_RIGHT:
|
||||||
|
filedata->data_sub->rotate = CELL_PHOTO_IMPORT_TEX_ROT_90;
|
||||||
|
break;
|
||||||
|
case CELL_SEARCH_ORIENTATION_BOTTOM_RIGHT:
|
||||||
|
filedata->data_sub->rotate = CELL_PHOTO_IMPORT_TEX_ROT_180;
|
||||||
|
break;
|
||||||
|
case CELL_SEARCH_ORIENTATION_BOTTOM_LEFT:
|
||||||
|
filedata->data_sub->rotate = CELL_PHOTO_IMPORT_TEX_ROT_270;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cellPhotoImportUtil.success("Media list dialog: selected entry '%s'. Copying to '%s'...", info.path, dst_path);
|
||||||
|
if (!fs::copy_file(info.path, dst_path, false))
|
||||||
|
{
|
||||||
|
cellPhotoImportUtil.error("Failed to copy '%s' to '%s'. Error = '%s'", info.path, dst_path, fs::g_tls_error);
|
||||||
|
result = CELL_PHOTO_IMPORT_ERROR_COPY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cellPhotoImportUtil.notice("Media list dialog was canceled");
|
||||||
|
}
|
||||||
|
|
||||||
|
pi_manager.is_busy = false;
|
||||||
|
pi_manager.func_finish(ppu, result, filedata, pi_manager.userdata);
|
||||||
|
return CELL_OK;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error != CELL_OK)
|
||||||
|
{
|
||||||
|
pi_manager.is_busy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
error_code cellPhotoImport(u32 version, vm::cptr<char> dstHddPath, vm::ptr<CellPhotoImportSetParam> param, u32 container, vm::ptr<CellPhotoImportFinishCallback> funcFinish, vm::ptr<void> userdata)
|
error_code cellPhotoImport(u32 version, vm::cptr<char> dstHddPath, vm::ptr<CellPhotoImportSetParam> param, u32 container, vm::ptr<CellPhotoImportFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||||
{
|
{
|
||||||
cellPhotoImportUtil.todo("cellPhotoImport(version=0x%x, dstHddPath=%s, param=*0x%x, container=0x%x, funcFinish=*0x%x, userdata=*0x%x)", version, dstHddPath, param, container, funcFinish, userdata);
|
cellPhotoImportUtil.todo("cellPhotoImport(version=0x%x, dstHddPath=%s, param=*0x%x, container=0x%x, funcFinish=*0x%x, userdata=*0x%x)", version, dstHddPath, param, container, funcFinish, userdata);
|
||||||
|
|
||||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
if (version != CELL_PHOTO_IMPORT_VERSION_CURRENT || !funcFinish || !param || !dstHddPath)
|
||||||
{
|
{
|
||||||
vm::var<CellPhotoImportFileData> filedata;
|
return CELL_PHOTO_IMPORT_ERROR_PARAM;
|
||||||
vm::var<CellPhotoImportFileDataSub> sub;
|
}
|
||||||
filedata->data_sub = sub;
|
|
||||||
funcFinish(ppu, CELL_OK, filedata, userdata);
|
|
||||||
return CELL_OK;
|
|
||||||
});
|
|
||||||
|
|
||||||
return CELL_OK;
|
if (container != 0xffffffff && false) // TODO
|
||||||
|
{
|
||||||
|
return CELL_PHOTO_IMPORT_ERROR_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& pi_manager = g_fxo->get<photo_import>();
|
||||||
|
std::lock_guard lock(pi_manager.mutex);
|
||||||
|
|
||||||
|
if (pi_manager.is_busy)
|
||||||
|
{
|
||||||
|
return CELL_PHOTO_IMPORT_ERROR_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pi_manager.param = *param;
|
||||||
|
pi_manager.func_finish = funcFinish;
|
||||||
|
pi_manager.userdata = userdata;
|
||||||
|
|
||||||
|
return select_photo(dstHddPath.get_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code cellPhotoImport2(u32 version, vm::cptr<char> dstHddPath, vm::ptr<CellPhotoImportSetParam> param, vm::ptr<CellPhotoImportFinishCallback> funcFinish, vm::ptr<void> userdata)
|
error_code cellPhotoImport2(u32 version, vm::cptr<char> dstHddPath, vm::ptr<CellPhotoImportSetParam> param, vm::ptr<CellPhotoImportFinishCallback> funcFinish, vm::ptr<void> userdata)
|
||||||
{
|
{
|
||||||
cellPhotoImportUtil.todo("cellPhotoImport2(version=0x%x, dstHddPath=%s, param=*0x%x, funcFinish=*0x%x, userdata=*0x%x)", version, dstHddPath, param, funcFinish, userdata);
|
cellPhotoImportUtil.todo("cellPhotoImport2(version=0x%x, dstHddPath=%s, param=*0x%x, funcFinish=*0x%x, userdata=*0x%x)", version, dstHddPath, param, funcFinish, userdata);
|
||||||
|
|
||||||
sysutil_register_cb([=](ppu_thread& ppu) -> s32
|
if (version != CELL_PHOTO_IMPORT_VERSION_CURRENT || !funcFinish || !param || !dstHddPath)
|
||||||
{
|
{
|
||||||
vm::var<CellPhotoImportFileData> filedata;
|
return CELL_PHOTO_IMPORT_ERROR_PARAM;
|
||||||
vm::var<CellPhotoImportFileDataSub> sub;
|
}
|
||||||
filedata->data_sub = sub;
|
|
||||||
funcFinish(ppu, CELL_OK, filedata, userdata);
|
|
||||||
return CELL_OK;
|
|
||||||
});
|
|
||||||
|
|
||||||
return CELL_OK;
|
auto& pi_manager = g_fxo->get<photo_import>();
|
||||||
|
std::lock_guard lock(pi_manager.mutex);
|
||||||
|
|
||||||
|
if (pi_manager.is_busy)
|
||||||
|
{
|
||||||
|
return CELL_PHOTO_IMPORT_ERROR_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pi_manager.param = *param;
|
||||||
|
pi_manager.func_finish = funcFinish;
|
||||||
|
pi_manager.userdata = userdata;
|
||||||
|
|
||||||
|
return select_photo(dstHddPath.get_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE(ppu_module_manager::cellPhotoImportUtil)("cellPhotoImportUtil", []()
|
DECLARE(ppu_module_manager::cellPhotoImportUtil)("cellPhotoImportUtil", []()
|
||||||
|
@ -34,6 +34,27 @@ namespace rsx
|
|||||||
{
|
{
|
||||||
if (fs::exists(entry.info.path))
|
if (fs::exists(entry.info.path))
|
||||||
{
|
{
|
||||||
|
// Fit the new image into the available space
|
||||||
|
if (entry.info.width > 0 && entry.info.height > 0)
|
||||||
|
{
|
||||||
|
const u16 target_width = image->w - (image->padding_left + image->padding_right);
|
||||||
|
const u16 target_height = image->h - (image->padding_top + image->padding_bottom);
|
||||||
|
const f32 target_ratio = target_width / static_cast<f32>(target_height);
|
||||||
|
const f32 image_ratio = entry.info.width / static_cast<f32>(entry.info.height);
|
||||||
|
const f32 convert_ratio = image_ratio / target_ratio;
|
||||||
|
|
||||||
|
if (convert_ratio > 1.0f)
|
||||||
|
{
|
||||||
|
const u16 new_padding = (target_height - target_height / convert_ratio) / 2;
|
||||||
|
image->set_padding(image->padding_left, image->padding_right, new_padding + image->padding_top, new_padding + image->padding_bottom);
|
||||||
|
}
|
||||||
|
else if (convert_ratio < 1.0f)
|
||||||
|
{
|
||||||
|
const u16 new_padding = (target_width - target_width * convert_ratio) / 2;
|
||||||
|
image->set_padding(image->padding_left + new_padding, image->padding_right + new_padding, image->padding_top, image->padding_bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
icon_data = std::make_unique<image_info>(entry.info.path.c_str());
|
icon_data = std::make_unique<image_info>(entry.info.path.c_str());
|
||||||
static_cast<image_view*>(image.get())->set_raw_image(icon_data.get());
|
static_cast<image_view*>(image.get())->set_raw_image(icon_data.get());
|
||||||
}
|
}
|
||||||
@ -263,7 +284,7 @@ namespace rsx
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
media_list_dialog::media_entry new_entry;
|
media_list_dialog::media_entry new_entry{};
|
||||||
parse_media_recursive(depth, media_path + "/" + dir_entry.name, dir_entry.name, type, new_entry);
|
parse_media_recursive(depth, media_path + "/" + dir_entry.name, dir_entry.name, type, new_entry);
|
||||||
if (new_entry.type != media_list_dialog::media_type::invalid)
|
if (new_entry.type != media_list_dialog::media_type::invalid)
|
||||||
{
|
{
|
||||||
@ -285,19 +306,12 @@ namespace rsx
|
|||||||
current_entry.info.path = media_path;
|
current_entry.info.path = media_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == media_list_dialog::media_type::photo)
|
|
||||||
{
|
|
||||||
// Let's restrict this to png and jpg for now
|
|
||||||
if (name.ends_with(".png") || name.ends_with(".jpg"))
|
|
||||||
{
|
|
||||||
current_entry.type = type;
|
|
||||||
rsx_log.notice("parse_media_recursive: Found photo '%s'", media_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Try to peek into the audio or video file
|
// Try to peek into the file
|
||||||
const s32 av_media_type = type == media_list_dialog::media_type::video ? 0 /*AVMEDIA_TYPE_VIDEO*/ : 1 /*AVMEDIA_TYPE_AUDIO*/;
|
const s32 av_media_type = type == media_list_dialog::media_type::photo ? -1
|
||||||
|
: type == media_list_dialog::media_type::video ? 0 /*AVMEDIA_TYPE_VIDEO*/
|
||||||
|
: 1 /*AVMEDIA_TYPE_AUDIO*/;
|
||||||
auto [success, info] = utils::get_media_info(media_path, av_media_type);
|
auto [success, info] = utils::get_media_info(media_path, av_media_type);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,7 @@ enum class localized_string_id
|
|||||||
RSX_OVERLAYS_OSK_DIALOG_ENTER_TEXT,
|
RSX_OVERLAYS_OSK_DIALOG_ENTER_TEXT,
|
||||||
RSX_OVERLAYS_OSK_DIALOG_ENTER_PASSWORD,
|
RSX_OVERLAYS_OSK_DIALOG_ENTER_PASSWORD,
|
||||||
RSX_OVERLAYS_MEDIA_DIALOG_TITLE,
|
RSX_OVERLAYS_MEDIA_DIALOG_TITLE,
|
||||||
|
RSX_OVERLAYS_MEDIA_DIALOG_TITLE_PHOTO_IMPORT,
|
||||||
RSX_OVERLAYS_MEDIA_DIALOG_EMPTY,
|
RSX_OVERLAYS_MEDIA_DIALOG_EMPTY,
|
||||||
RSX_OVERLAYS_LIST_SELECT,
|
RSX_OVERLAYS_LIST_SELECT,
|
||||||
RSX_OVERLAYS_LIST_CANCEL,
|
RSX_OVERLAYS_LIST_CANCEL,
|
||||||
|
@ -55,6 +55,7 @@ private:
|
|||||||
case localized_string_id::RSX_OVERLAYS_OSK_DIALOG_ENTER_TEXT: return tr("[Enter Text]", "OSK Dialog");
|
case localized_string_id::RSX_OVERLAYS_OSK_DIALOG_ENTER_TEXT: return tr("[Enter Text]", "OSK Dialog");
|
||||||
case localized_string_id::RSX_OVERLAYS_OSK_DIALOG_ENTER_PASSWORD: return tr("[Enter Password]", "OSK Dialog");
|
case localized_string_id::RSX_OVERLAYS_OSK_DIALOG_ENTER_PASSWORD: return tr("[Enter Password]", "OSK Dialog");
|
||||||
case localized_string_id::RSX_OVERLAYS_MEDIA_DIALOG_TITLE: return tr("Select media", "Media dialog");
|
case localized_string_id::RSX_OVERLAYS_MEDIA_DIALOG_TITLE: return tr("Select media", "Media dialog");
|
||||||
|
case localized_string_id::RSX_OVERLAYS_MEDIA_DIALOG_TITLE_PHOTO_IMPORT: return tr("Select photo to import", "Media dialog");
|
||||||
case localized_string_id::RSX_OVERLAYS_MEDIA_DIALOG_EMPTY: return tr("No media found.", "Media dialog");
|
case localized_string_id::RSX_OVERLAYS_MEDIA_DIALOG_EMPTY: return tr("No media found.", "Media dialog");
|
||||||
case localized_string_id::RSX_OVERLAYS_LIST_SELECT: return tr("Enter", "Enter Dialog List");
|
case localized_string_id::RSX_OVERLAYS_LIST_SELECT: return tr("Enter", "Enter Dialog List");
|
||||||
case localized_string_id::RSX_OVERLAYS_LIST_CANCEL: return tr("Back", "Cancel Dialog List");
|
case localized_string_id::RSX_OVERLAYS_LIST_CANCEL: return tr("Back", "Cancel Dialog List");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user