From 953e31cbe89bedb0fc55099435eff3eda7eda216 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 30 Dec 2025 09:10:20 +0100 Subject: [PATCH] Adjust media list dialog for larger folder depth Use shared_ptr to fix crashes when navigating deeper folders --- rpcs3/Emu/Cell/Modules/cellMusic.cpp | 2 +- rpcs3/Emu/Cell/Modules/cellMusicDecode.cpp | 2 +- rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp | 2 +- .../Overlays/overlay_media_list_dialog.cpp | 74 ++++++++++++------- .../RSX/Overlays/overlay_media_list_dialog.h | 10 +-- 5 files changed, 56 insertions(+), 34 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellMusic.cpp b/rpcs3/Emu/Cell/Modules/cellMusic.cpp index 83937f7d16..c23bf274b0 100644 --- a/rpcs3/Emu/Cell/Modules/cellMusic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMusic.cpp @@ -215,7 +215,7 @@ error_code cell_music_select_contents() const std::string vfs_dir_path = vfs::get("/dev_hdd0/music"); const std::string title = get_localized_string(localized_string_id::RSX_OVERLAYS_MEDIA_DIALOG_TITLE); - error_code error = rsx::overlays::show_media_list_dialog(rsx::overlays::media_list_dialog::media_type::audio, vfs_dir_path, title, + error_code error = rsx::overlays::show_media_list_dialog(rsx::overlays::media_list_dialog::media_type::audio, music_selection_context::max_depth, vfs_dir_path, title, [&music](s32 status, utils::media_info info) { sysutil_register_cb([&music, info = std::move(info), status](ppu_thread& ppu) -> s32 diff --git a/rpcs3/Emu/Cell/Modules/cellMusicDecode.cpp b/rpcs3/Emu/Cell/Modules/cellMusicDecode.cpp index c938f723b1..b7f21b90ad 100644 --- a/rpcs3/Emu/Cell/Modules/cellMusicDecode.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMusicDecode.cpp @@ -134,7 +134,7 @@ error_code cell_music_decode_select_contents() const std::string vfs_dir_path = vfs::get("/dev_hdd0/music"); const std::string title = get_localized_string(localized_string_id::RSX_OVERLAYS_MEDIA_DIALOG_TITLE); - error_code error = rsx::overlays::show_media_list_dialog(rsx::overlays::media_list_dialog::media_type::audio, vfs_dir_path, title, + error_code error = rsx::overlays::show_media_list_dialog(rsx::overlays::media_list_dialog::media_type::audio, music_selection_context::max_depth, vfs_dir_path, title, [&dec](s32 status, utils::media_info info) { sysutil_register_cb([&dec, info = std::move(info), status](ppu_thread& ppu) -> s32 diff --git a/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp b/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp index d56db1f060..fbb287d311 100644 --- a/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPhotoImport.cpp @@ -142,7 +142,7 @@ error_code select_photo(std::string dst_dir) 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, + error_code error = rsx::overlays::show_media_list_dialog(rsx::overlays::media_list_dialog::media_type::photo, umax, 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 diff --git a/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.cpp b/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.cpp index cc7affc983..bedbf652c7 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.cpp @@ -8,6 +8,24 @@ #include "Utilities/StrUtil.h" #include "Utilities/Thread.h" +template <> +void fmt_class_string::format(std::string& out, u64 arg) +{ + format_enum(out, arg, [](rsx::overlays::media_list_dialog::media_type arg) + { + switch (arg) + { + case rsx::overlays::media_list_dialog::media_type::invalid: return "invalid"; + case rsx::overlays::media_list_dialog::media_type::directory: return "directory"; + case rsx::overlays::media_list_dialog::media_type::audio: return "audio"; + case rsx::overlays::media_list_dialog::media_type::video: return "video"; + case rsx::overlays::media_list_dialog::media_type::photo: return "photo"; + } + + return unknown; + }); +} + namespace rsx { namespace overlays @@ -203,7 +221,7 @@ namespace rsx return result; } - s32 media_list_dialog::show(media_entry* root, media_entry& result, const std::string& title, u32 focused, bool enable_overlay) + s32 media_list_dialog::show(std::shared_ptr root, media_entry& result, const std::string& title, u32 focused, bool enable_overlay) { auto ref = g_fxo->get().get(uid); @@ -237,7 +255,7 @@ namespace rsx { focused = 0; ensure(static_cast(return_code) < m_media->children.size()); - m_media = &m_media->children[return_code]; + m_media = m_media->children[return_code]; rsx_log.notice("Media dialog: selected entry: %d ('%s')", return_code, m_media->path); continue; } @@ -287,9 +305,10 @@ namespace rsx m_list = std::make_unique(virtual_width - 2 * 20, 540); m_list->set_pos(20, 85); - for (const media_entry& child : m_media->children) + for (const auto& child : m_media->children) { - std::unique_ptr entry = std::make_unique(child); + ensure(!!child); + std::unique_ptr entry = std::make_unique(*child); m_list->add_entry(entry); } @@ -321,9 +340,11 @@ namespace rsx static constexpr auto thread_name = "MediaList Thread"sv; }; - void parse_media_recursive(u32 depth, const std::string& media_path, const std::string& name, media_list_dialog::media_type type, media_list_dialog::media_entry& current_entry) + void parse_media_recursive(u32 depth, u32 max_depth, const std::string& media_path, const std::string& name, media_list_dialog::media_type type, std::shared_ptr current_entry) { - if (depth++ > music_selection_context::max_depth) + ensure(!!current_entry); + + if (depth++ > max_depth && max_depth != umax) { return; } @@ -339,26 +360,27 @@ namespace rsx const std::string unescaped_name = vfs::unescape(dir_entry.name); - media_list_dialog::media_entry new_entry{}; - parse_media_recursive(depth, media_path + "/" + dir_entry.name, unescaped_name, type, new_entry); - if (new_entry.type != media_list_dialog::media_type::invalid) + auto new_entry = std::make_shared(); + parse_media_recursive(depth, max_depth, media_path + "/" + dir_entry.name, unescaped_name, type, new_entry); + if (new_entry->type != media_list_dialog::media_type::invalid) { - new_entry.parent = ¤t_entry; - new_entry.index = ::narrow(current_entry.children.size()); - current_entry.children.emplace_back(std::move(new_entry)); + rsx_log.notice("parse_media_recursive: found '%s' (type=%s)", dir_entry.name, new_entry->type); + new_entry->parent = current_entry; + new_entry->index = ::narrow(current_entry->children.size()); + current_entry->children.emplace_back(std::move(new_entry)); } } // Only keep directories that contain valid entries - if (current_entry.children.empty()) + if (current_entry->children.empty()) { rsx_log.notice("parse_media_recursive: No matches in directory '%s'", media_path); } else { - rsx_log.notice("parse_media_recursive: Found %d matches in directory '%s'", current_entry.children.size(), media_path); - current_entry.type = media_list_dialog::media_type::directory; - current_entry.info.path = media_path; + rsx_log.notice("parse_media_recursive: Found %d matches in directory '%s'", current_entry->children.size(), media_path); + current_entry->type = media_list_dialog::media_type::directory; + current_entry->info.path = media_path; } } else @@ -370,20 +392,20 @@ namespace rsx auto [success, info] = utils::get_media_info(media_path, av_media_type); if (success) { - current_entry.type = type; - current_entry.info = std::move(info); + current_entry->type = type; + current_entry->info = std::move(info); rsx_log.notice("parse_media_recursive: Found media '%s'", media_path); } } - if (current_entry.type != media_list_dialog::media_type::invalid) + if (current_entry->type != media_list_dialog::media_type::invalid) { - current_entry.path = media_path; - current_entry.name = name; + current_entry->path = media_path; + current_entry->name = name; } } - error_code show_media_list_dialog(media_list_dialog::media_type type, const std::string& path, const std::string& title, std::function on_finished) + error_code show_media_list_dialog(media_list_dialog::media_type type, u32 max_depth, const std::string& path, const std::string& title, std::function on_finished) { rsx_log.todo("show_media_list_dialog(type=%d, path='%s', title='%s', on_finished=%d)", static_cast(type), path, title, !!on_finished); @@ -394,12 +416,12 @@ namespace rsx g_fxo->get>()([=]() { - media_list_dialog::media_entry root_media_entry{}; - root_media_entry.type = media_list_dialog::media_type::directory; + auto root_media_entry = std::make_shared(); + root_media_entry->type = media_list_dialog::media_type::directory; if (fs::is_dir(path)) { - parse_media_recursive(0, path, title, type, root_media_entry); + parse_media_recursive(0, max_depth, path, title, type, root_media_entry); } else { @@ -412,7 +434,7 @@ namespace rsx if (auto manager = g_fxo->try_get()) { - result = manager->create()->show(&root_media_entry, media, title, focused, true); + result = manager->create()->show(root_media_entry, media, title, focused, true); } else { diff --git a/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.h b/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.h index 6a5d39b3fa..e2656d728f 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.h @@ -29,8 +29,8 @@ namespace rsx utils::media_info info; u32 index = 0; - media_entry* parent = nullptr; - std::vector children; + std::shared_ptr parent; + std::vector> children; }; media_list_dialog(); @@ -39,7 +39,7 @@ namespace rsx compiled_resource get_compiled() override; - s32 show(media_entry* root, media_entry& result, const std::string& title, u32 focused, bool enable_overlay); + s32 show(std::shared_ptr root, media_entry& result, const std::string& title, u32 focused, bool enable_overlay); private: void reload(const std::string& title, u32 focused); @@ -53,7 +53,7 @@ namespace rsx std::unique_ptr icon_data; }; - media_entry* m_media = nullptr; + std::shared_ptr m_media; std::unique_ptr m_dim_background; std::unique_ptr m_list; @@ -61,6 +61,6 @@ namespace rsx std::unique_ptr