diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 95536540f5e1..c5f7d5c70b25 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -827,14 +827,14 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_intrp_func_t ptr = return; } - size = utils::align(size + addr % 4, 4); - addr &= -4; - if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm) { return; } + size = utils::align(size + addr % 4, 4); + addr &= -4; + // Initialize interpreter cache while (size) { diff --git a/rpcs3/Emu/RSX/Overlays/FriendsList/overlay_friends_list_dialog.cpp b/rpcs3/Emu/RSX/Overlays/FriendsList/overlay_friends_list_dialog.cpp index 2df72329bf5c..f96505ea3c49 100644 --- a/rpcs3/Emu/RSX/Overlays/FriendsList/overlay_friends_list_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/FriendsList/overlay_friends_list_dialog.cpp @@ -1,7 +1,6 @@ #include "stdafx.h" #include "../overlay_manager.h" #include "overlay_friends_list_dialog.h" -#include "Emu/System.h" #include "Emu/NP/rpcn_config.h" #include "Emu/vfs_config.h" @@ -306,11 +305,11 @@ namespace rsx } } - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); return; } case pad_button::circle: - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); close_dialog = true; break; case pad_button::square: @@ -359,7 +358,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } } diff --git a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_message_box.cpp b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_message_box.cpp index 4d9196ad0784..ed42f4f815d4 100644 --- a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_message_box.cpp +++ b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_message_box.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" #include "overlay_home_menu_message_box.h" -#include "Emu/System.h" #include "Emu/system_config.h" namespace rsx @@ -77,7 +76,7 @@ namespace rsx { case pad_button::cross: { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); if (m_on_accept) { m_on_accept(); @@ -86,7 +85,7 @@ namespace rsx } case pad_button::circle: { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); if (m_on_cancel) { m_on_cancel(); diff --git a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_page.cpp b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_page.cpp index f298de0a8114..81c1ebecbab9 100644 --- a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_page.cpp +++ b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_page.cpp @@ -160,7 +160,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise if (!is_auto_repeat || auto_repeat_interval_ms >= user_interface::m_auto_repeat_ms_interval_default) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); } return func(button_press); } @@ -169,7 +169,7 @@ namespace rsx } case pad_button::circle: { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); if (parent) { set_current_page(parent); @@ -244,7 +244,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise if (!is_auto_repeat || auto_repeat_interval_ms >= user_interface::m_auto_repeat_ms_interval_default) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } return page_navigation::stay; } diff --git a/rpcs3/Emu/RSX/Overlays/Network/overlay_recvmessage_dialog.cpp b/rpcs3/Emu/RSX/Overlays/Network/overlay_recvmessage_dialog.cpp index cb1837b78d42..278510e8a979 100644 --- a/rpcs3/Emu/RSX/Overlays/Network/overlay_recvmessage_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/Network/overlay_recvmessage_dialog.cpp @@ -127,11 +127,11 @@ namespace rsx { return_code = selection_code::error; } - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); close_dialog = true; break; case pad_button::circle: - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); close_dialog = true; break; case pad_button::dpad_up: @@ -167,7 +167,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } } diff --git a/rpcs3/Emu/RSX/Overlays/Network/overlay_sendmessage_dialog.cpp b/rpcs3/Emu/RSX/Overlays/Network/overlay_sendmessage_dialog.cpp index 5369afb097f2..5d2d5c1beff9 100644 --- a/rpcs3/Emu/RSX/Overlays/Network/overlay_sendmessage_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/Network/overlay_sendmessage_dialog.cpp @@ -82,7 +82,7 @@ namespace rsx if (m_list->m_items.empty() || is_auto_repeat) break; - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); if (!get_current_selection().empty()) { @@ -95,7 +95,7 @@ namespace rsx close_dialog = true; break; case pad_button::circle: - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); close_dialog = true; break; case pad_button::dpad_up: @@ -131,7 +131,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } } diff --git a/rpcs3/Emu/RSX/Overlays/Trophies/overlay_trophy_list_dialog.cpp b/rpcs3/Emu/RSX/Overlays/Trophies/overlay_trophy_list_dialog.cpp index 786771635585..ea47ad80b6f3 100644 --- a/rpcs3/Emu/RSX/Overlays/Trophies/overlay_trophy_list_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/Trophies/overlay_trophy_list_dialog.cpp @@ -132,7 +132,7 @@ namespace rsx switch (button_press) { case pad_button::circle: - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); close_dialog = true; break; case pad_button::square: @@ -172,7 +172,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.cpp b/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.cpp index 2cf113243af1..cc7affc98326 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_media_list_dialog.cpp @@ -4,7 +4,6 @@ #include "overlay_media_list_dialog.h" #include "Emu/Cell/Modules/cellMusic.h" -#include "Emu/System.h" #include "Emu/VFS.h" #include "Utilities/StrUtil.h" #include "Utilities/Thread.h" @@ -154,13 +153,13 @@ namespace rsx return_code = m_list->get_selected_index(); m_stop_input_loop = true; play_cursor_sound = false; - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); break; case pad_button::circle: return_code = selection_code::canceled; m_stop_input_loop = true; play_cursor_sound = false; - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); break; case pad_button::dpad_up: m_list->select_previous(); @@ -182,7 +181,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise if (play_cursor_sound && (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp index 578967de1a25..a0be8ce5cf1c 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp @@ -155,7 +155,7 @@ namespace rsx return_code = CELL_MSGDIALOG_BUTTON_YES; } - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); break; } case pad_button::circle: @@ -175,7 +175,7 @@ namespace rsx return_code = CELL_MSGDIALOG_BUTTON_NO; } - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); break; } default: return; @@ -238,10 +238,7 @@ namespace rsx if (!type.se_mute_on) { - if (type.se_normal) - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_system_ok.wav"); - else - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_system_ng.wav"); + play_sound(type.se_normal ? sound_effect::dialog_ok : sound_effect::dialog_error); } set_text(text); diff --git a/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp b/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp index 82047a72bd30..428c68a5417c 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp @@ -823,7 +823,7 @@ namespace rsx } case pad_button::start: { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_oskenter.wav"); + play_sound(sound_effect::osk_accept); Close(CELL_OSKDIALOG_CLOSE_CONFIRM); play_cursor_sound = false; break; @@ -840,7 +840,7 @@ namespace rsx } case pad_button::cross: { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_oskenter.wav"); + play_sound(sound_effect::osk_accept); on_accept(); m_reset_pulse = true; play_cursor_sound = false; @@ -848,7 +848,7 @@ namespace rsx } case pad_button::circle: { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_oskcancel.wav"); + play_sound(sound_effect::osk_cancel); Close(CELL_OSKDIALOG_CLOSE_CANCEL); play_cursor_sound = false; break; @@ -890,7 +890,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise if (play_cursor_sound && (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } if (m_reset_pulse) diff --git a/rpcs3/Emu/RSX/Overlays/overlay_save_dialog.cpp b/rpcs3/Emu/RSX/Overlays/overlay_save_dialog.cpp index 86e9905f2f46..604dee7fc42b 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_save_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_save_dialog.cpp @@ -2,7 +2,6 @@ #include "overlay_save_dialog.h" #include "overlay_video.h" #include "Utilities/date_time.h" -#include "Emu/System.h" namespace rsx { @@ -133,11 +132,11 @@ namespace rsx if (m_no_saves) break; return_code = m_list->get_selected_index(); - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); close_dialog = true; break; case pad_button::circle: - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); close_dialog = true; break; case pad_button::dpad_up: @@ -173,7 +172,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_trophy_notification.cpp b/rpcs3/Emu/RSX/Overlays/overlay_trophy_notification.cpp index 595828afd9cd..ba927095c8e5 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_trophy_notification.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_trophy_notification.cpp @@ -1,7 +1,6 @@ #include "stdafx.h" #include "overlay_trophy_notification.h" #include "Emu/Cell/ErrorCodes.h" -#include "Emu/System.h" namespace rsx { @@ -70,7 +69,7 @@ namespace rsx { // First tick creation_time_us = timestamp_us; - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_trophy.wav"); + play_sound(sound_effect::trophy); return; } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_user_list_dialog.cpp b/rpcs3/Emu/RSX/Overlays/overlay_user_list_dialog.cpp index 186ac0ee8341..f534ce558769 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_user_list_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_user_list_dialog.cpp @@ -113,11 +113,11 @@ namespace rsx { return_code = selection_code::error; } - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav"); + play_sound(sound_effect::accept); close_dialog = true; break; case pad_button::circle: - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav"); + play_sound(sound_effect::cancel); close_dialog = true; break; case pad_button::dpad_up: @@ -153,7 +153,7 @@ namespace rsx // Play a sound unless this is a fast auto repeat which would induce a nasty noise else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default) { - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav"); + play_sound(sound_effect::cursor); } } diff --git a/rpcs3/Emu/RSX/Overlays/overlays.cpp b/rpcs3/Emu/RSX/Overlays/overlays.cpp index d24c8550f353..f44647daa00a 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlays.cpp @@ -15,6 +15,33 @@ namespace rsx { namespace overlays { + std::string get_sound_filepath(sound_effect sound) + { + const auto get_sound_filename = [sound]() + { + switch (sound) + { + case sound_effect::cursor: return "snd_cursor"sv; + case sound_effect::accept: return "snd_decide"sv; + case sound_effect::cancel: return "snd_cancel"sv; + case sound_effect::osk_accept: return "snd_oskenter"sv; + case sound_effect::osk_cancel: return "snd_oskcancel"sv; + case sound_effect::dialog_ok: return "snd_system_ok"sv; + case sound_effect::dialog_error: return "snd_system_ng"sv; + case sound_effect::trophy: return "snd_trophy"sv; + } + + fmt::throw_exception("Unreachable (sound=%d)", static_cast(sound)); + }; + + return fmt::format("%ssounds/%s.wav", fs::get_config_dir(), get_sound_filename()); + } + + void play_sound(sound_effect sound, std::optional volume) + { + Emu.GetCallbacks().play_sound(get_sound_filepath(sound), volume); + } + thread_local DECLARE(user_interface::g_thread_bit) = 0; u32 user_interface::alloc_thread_bit() diff --git a/rpcs3/Emu/RSX/Overlays/overlays.h b/rpcs3/Emu/RSX/Overlays/overlays.h index 9bcef524828f..2aac6798d2d9 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.h +++ b/rpcs3/Emu/RSX/Overlays/overlays.h @@ -17,6 +17,21 @@ namespace rsx { namespace overlays { + enum class sound_effect + { + cursor, + accept, + cancel, + osk_accept, + osk_cancel, + dialog_ok, + dialog_error, + trophy, + }; + + std::string get_sound_filepath(sound_effect sound); + void play_sound(sound_effect sound, std::optional volume = std::nullopt); + // Bitfield of UI signals to overlay manager enum status_bits : u32 { diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 0c26d09a4b33..7c79a1931b6a 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -101,7 +101,7 @@ struct EmuCallbacks std::function get_localized_string; std::function get_localized_u32string; std::function get_localized_setting; - std::function play_sound; + std::function)> play_sound; std::function get_image_info; // (filename, sub_type, width, height, CellSearchOrientation) std::function get_scaled_image; // (filename, target_width, target_height, width, height, dst, force_fit) std::string(*resolve_path)(std::string_view) = [](std::string_view arg){ return std::string{arg}; }; // Resolve path using Qt diff --git a/rpcs3/headless_application.cpp b/rpcs3/headless_application.cpp index 43de0e108ffa..58047671a644 100644 --- a/rpcs3/headless_application.cpp +++ b/rpcs3/headless_application.cpp @@ -169,7 +169,7 @@ void headless_application::InitializeCallbacks() callbacks.get_localized_u32string = [](localized_string_id, const char*) -> std::u32string { return {}; }; callbacks.get_localized_setting = [](const cfg::_base*, u32) -> std::string { return {}; }; - callbacks.play_sound = [](const std::string&){}; + callbacks.play_sound = [](const std::string&, std::optional){}; callbacks.add_breakpoint = [](u32 /*addr*/){}; callbacks.display_sleep_control_supported = [](){ return false; }; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index fe26cc196822..b5ffb8ebd807 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -430,6 +430,9 @@ true + + true + true @@ -718,6 +721,9 @@ true + + true + true @@ -851,6 +857,7 @@ + @@ -1311,6 +1318,16 @@ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent" + + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent" + Moc%27ing %(Identity)... + .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent" + $(QTDIR)\bin\moc.exe;%(FullPath) + $(QTDIR)\bin\moc.exe;%(FullPath) + $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing %(Identity)... diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 7c98b7c735aa..aa90e50cd056 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -205,6 +205,9 @@ {149c596b-83e7-43f8-b5db-6108694434ef} + + {640b7d83-1522-4384-8bf7-a4fbd5873ae7} + @@ -738,6 +741,15 @@ Generated Files\Release + + Gui\sound effect manager + + + Generated Files\Debug + + + Generated Files\Release + Gui\screenshot manager @@ -1627,6 +1639,9 @@ Gui\screenshot manager + + Gui\sound effect manager + Gui\dimensions diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index f194b7550b58..43c00249051e 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -99,6 +99,7 @@ add_library(rpcs3_ui STATIC shortcut_handler.cpp shortcut_settings.cpp skylander_dialog.cpp + sound_effect_manager_dialog.cpp syntax_highlighter.cpp system_cmd_dialog.cpp table_item_delegate.cpp diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 5298ac2b98a8..df6aac317a95 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -447,7 +447,7 @@ void gs_frame::toggle_recording() // Play a sound if (const std::string sound_path = fs::get_config_dir() + "sounds/snd_recording.wav"; fs::is_file(sound_path)) { - Emu.GetCallbacks().play_sound(sound_path); + Emu.GetCallbacks().play_sound(sound_path, std::nullopt); } else { @@ -1070,7 +1070,7 @@ void gs_frame::take_screenshot(std::vector&& data, u32 sshot_width, u32 ssho { if (const std::string sound_path = fs::get_config_dir() + "sounds/snd_screenshot.wav"; fs::is_file(sound_path)) { - Emu.GetCallbacks().play_sound(sound_path); + Emu.GetCallbacks().play_sound(sound_path, std::nullopt); } else { diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index 82f29fcdbdaf..e028aaefa828 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -743,9 +743,9 @@ void gui_application::InitializeCallbacks() return m_emu_settings->GetLocalizedSetting(node, enum_index); }; - callbacks.play_sound = [this](const std::string& path) + callbacks.play_sound = [this](const std::string& path, std::optional volume) { - Emu.CallFromMainThread([this, path]() + Emu.CallFromMainThread([this, path, volume]() { if (fs::is_file(path)) { @@ -758,12 +758,12 @@ void gui_application::InitializeCallbacks() // Create a new sound effect. Re-using the same object seems to be broken for some users starting with Qt 6.6.3. std::unique_ptr sound_effect = std::make_unique(); sound_effect->setSource(QUrl::fromLocalFile(QString::fromStdString(path))); - sound_effect->setVolume(audio::get_volume()); + sound_effect->setVolume(volume ? *volume : audio::get_volume()); sound_effect->play(); m_sound_effects.push_back(std::move(sound_effect)); } - }); + }, nullptr, false); }; if (m_show_gui) // If this is false, we already have a fallback in the main_application. diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index 38767ceabbee..f3f90121aadc 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -44,6 +44,7 @@ #include "vfs_tool_dialog.h" #include "welcome_dialog.h" #include "music_player_dialog.h" +#include "sound_effect_manager_dialog.h" #include #include @@ -3037,6 +3038,12 @@ void main_window::CreateConnects() screenshot_manager->show(); }); + connect(ui->actionManage_SoundEffects, &QAction::triggered, this, [this] + { + sound_effect_manager_dialog* dlg = new sound_effect_manager_dialog(); + dlg->show(); + }); + connect(ui->toolsCgDisasmAct, &QAction::triggered, this, [this] { cg_disasm_window* cgdw = new cg_disasm_window(m_gui_settings); diff --git a/rpcs3/rpcs3qt/main_window.ui b/rpcs3/rpcs3qt/main_window.ui index e10abf4668f0..5ef0b98f2549 100644 --- a/rpcs3/rpcs3qt/main_window.ui +++ b/rpcs3/rpcs3qt/main_window.ui @@ -306,6 +306,7 @@ + @@ -1442,6 +1443,11 @@ Music Player + + + Sound Effects + + diff --git a/rpcs3/rpcs3qt/sound_effect_manager_dialog.cpp b/rpcs3/rpcs3qt/sound_effect_manager_dialog.cpp new file mode 100644 index 000000000000..cfd93246eb97 --- /dev/null +++ b/rpcs3/rpcs3qt/sound_effect_manager_dialog.cpp @@ -0,0 +1,137 @@ +#include "stdafx.h" +#include "sound_effect_manager_dialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_CHANNEL(gui_log, "GUI"); + +sound_effect_manager_dialog::sound_effect_manager_dialog(QWidget* parent) + : QDialog(parent) +{ + setWindowTitle(tr("Sound Effects")); + setAttribute(Qt::WA_DeleteOnClose); + + QLabel* description = new QLabel(tr("You can import sound effects for the RPCS3 overlays here.\nThe file format is .wav and you should try to make the sounds as short as possible."), this); + + QVBoxLayout* main_layout = new QVBoxLayout(this); + main_layout->addWidget(description); + + const auto add_sound_widget = [this, main_layout](rsx::overlays::sound_effect sound) + { + ensure(!m_widgets.contains(sound)); + + QString name; + switch (sound) + { + case rsx::overlays::sound_effect::cursor: name = tr("Cursor"); break; + case rsx::overlays::sound_effect::accept: name = tr("Accept"); break; + case rsx::overlays::sound_effect::cancel: name = tr("Cancel"); break; + case rsx::overlays::sound_effect::osk_accept: name = tr("Onscreen keyboard accept"); break; + case rsx::overlays::sound_effect::osk_cancel: name = tr("Onscreen keyboard cancel"); break; + case rsx::overlays::sound_effect::dialog_ok: name = tr("Dialog popup"); break; + case rsx::overlays::sound_effect::dialog_error: name = tr("Error dialog popup"); break; + case rsx::overlays::sound_effect::trophy: name = tr("Trophy popup"); break; + } + + QPushButton* button = new QPushButton("", this); + connect(button, &QAbstractButton::clicked, this, [this, button, sound, name]() + { + const std::string path = rsx::overlays::get_sound_filepath(sound); + if (fs::is_file(path)) + { + if (QMessageBox::question(this, tr("Remove sound effect?"), tr("Do you really want to remove the '%0' sound effect.").arg(name)) == QMessageBox::Yes) + { + if (!fs::remove_file(path)) + { + gui_log.error("Failed to remove sound effect file '%s': %s", path, fs::g_tls_error); + } + + update_widgets(); + } + } + else + { + const QString src_path = QFileDialog::getOpenFileName(this, tr("Select Audio File to Import"), "", tr("WAV (*.wav);;")); + if (!src_path.isEmpty()) + { + if (!fs::copy_file(src_path.toStdString(), path, true)) + { + gui_log.error("Failed to import sound effect file '%s' to '%s': %s", src_path, path, fs::g_tls_error); + } + update_widgets(); + } + } + }); + + QPushButton* play_button = new QPushButton(this); + play_button->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaPlay)); + play_button->setIconSize(QSize(16, 16)); + play_button->setFixedSize(24, 24); + connect(play_button, &QAbstractButton::clicked, this, [sound]() + { + rsx::overlays::play_sound(sound, 1.0f); + }); + + QHBoxLayout* layout = new QHBoxLayout(this); + layout->addWidget(button); + layout->addWidget(play_button); + layout->addStretch(1); + + QGroupBox* gb = new QGroupBox(name, this); + gb->setLayout(layout); + + main_layout->addWidget(gb); + + m_widgets[sound] = { + .button = button, + .play_button = play_button + }; + }; + + add_sound_widget(rsx::overlays::sound_effect::cursor); + add_sound_widget(rsx::overlays::sound_effect::accept); + add_sound_widget(rsx::overlays::sound_effect::cancel); + add_sound_widget(rsx::overlays::sound_effect::osk_accept); + add_sound_widget(rsx::overlays::sound_effect::osk_cancel); + add_sound_widget(rsx::overlays::sound_effect::dialog_ok); + add_sound_widget(rsx::overlays::sound_effect::dialog_error); + add_sound_widget(rsx::overlays::sound_effect::trophy); + + setLayout(main_layout); + update_widgets(); + resize(sizeHint()); +} + +sound_effect_manager_dialog::~sound_effect_manager_dialog() +{ +} + +void sound_effect_manager_dialog::update_widgets() +{ + for (auto& [sound, widget] : m_widgets) + { + const bool file_exists = fs::is_file(rsx::overlays::get_sound_filepath(sound)); + + widget.play_button->setEnabled(file_exists); + + if (file_exists) + { + widget.button->setText(tr("Remove")); + widget.button->setIcon(QApplication::style()->standardIcon(QStyle::SP_TrashIcon)); + widget.button->setIconSize(QSize(16, 16)); + } + else + { + widget.button->setText(tr("Import")); + widget.button->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogOpenButton)); + widget.button->setIconSize(QSize(16, 16)); + } + } +} diff --git a/rpcs3/rpcs3qt/sound_effect_manager_dialog.h b/rpcs3/rpcs3qt/sound_effect_manager_dialog.h new file mode 100644 index 000000000000..e8e52440f1cf --- /dev/null +++ b/rpcs3/rpcs3qt/sound_effect_manager_dialog.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Emu/RSX/Overlays/overlays.h" + +#include +#include + +class sound_effect_manager_dialog : public QDialog +{ + Q_OBJECT + +public: + explicit sound_effect_manager_dialog(QWidget* parent = nullptr); + ~sound_effect_manager_dialog(); + +private: + void update_widgets(); + + struct widget + { + QPushButton* button = nullptr; + QPushButton* play_button = nullptr; + }; + + std::map m_widgets; +}; diff --git a/rpcs3/rpcs3qt/trophy_notification_helper.cpp b/rpcs3/rpcs3qt/trophy_notification_helper.cpp index 910b16ffcc71..87b69c42b2eb 100644 --- a/rpcs3/rpcs3qt/trophy_notification_helper.cpp +++ b/rpcs3/rpcs3qt/trophy_notification_helper.cpp @@ -31,7 +31,7 @@ s32 trophy_notification_helper::ShowTrophyNotification(const SceNpTrophyDetails& trophy_notification->move(m_game_window->mapToGlobal(QPoint(0, 0))); trophy_notification->show(); - Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_trophy.wav"); + Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_trophy.wav", std::nullopt); }); return 0;