diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index 10863c0..94c5eb0 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -119,7 +119,7 @@ endif() set(UNLEASHED_RECOMP_APU_CXX_SOURCES "apu/audio.cpp" - "apu/embedded_player.cpp" + "apu/embedded_player.cpp" "apu/driver/sdl2_driver.cpp" ) @@ -149,16 +149,16 @@ set(UNLEASHED_RECOMP_PATCHES_CXX_SOURCES set(UNLEASHED_RECOMP_UI_CXX_SOURCES "ui/achievement_menu.cpp" - "ui/achievement_overlay.cpp" + "ui/achievement_overlay.cpp" "ui/black_bar.cpp" "ui/button_guide.cpp" "ui/fader.cpp" - "ui/game_window.cpp" + "ui/game_window.cpp" "ui/imgui_utils.cpp" "ui/installer_wizard.cpp" "ui/message_window.cpp" "ui/options_menu.cpp" - "ui/options_menu_thumbnails.cpp" + "ui/options_menu_thumbnails.cpp" "ui/tv_static.cpp" ) @@ -180,7 +180,7 @@ set(UNLEASHED_RECOMP_INSTALL_CXX_SOURCES set(UNLEASHED_RECOMP_USER_CXX_SOURCES "user/achievement_data.cpp" "user/achievement_manager.cpp" - "user/config.cpp" + "user/config.cpp" "user/registry.cpp" "user/paths.cpp" "user/persistent_data.cpp" @@ -250,11 +250,11 @@ set(UNLEASHED_RECOMP_CXX_SOURCES ${UNLEASHED_RECOMP_USER_CXX_SOURCES} ${UNLEASHED_RECOMP_MOD_CXX_SOURCES} ${UNLEASHED_RECOMP_THIRDPARTY_SOURCES} -) +) -include("version.cmake") - -set(VERSION_TXT "${PROJECT_SOURCE_DIR}/res/version.txt") +include("version.cmake") + +set(VERSION_TXT "${PROJECT_SOURCE_DIR}/res/version.txt") # Only show Git info and build type if not Release. set(SHOW_GIT_INFO_AND_BUILD_TYPE 0) @@ -270,43 +270,43 @@ GenerateVersionSources( BUILD_TYPE ${CMAKE_BUILD_TYPE} SHOW_GIT_INFO ${SHOW_GIT_INFO_AND_BUILD_TYPE} SHOW_BUILD_TYPE ${SHOW_GIT_INFO_AND_BUILD_TYPE} -) +) if (WIN32) - # Create binary version number for Win32 integer attributes. - CreateVersionString( - VERSION_TXT ${VERSION_TXT} - OUTPUT_CSV 1 - OUTPUT_VAR WIN32_VERSION_BINARY - ) - - # Create string version number for Win32 detailed attributes. - CreateVersionString( - VERSION_TXT ${VERSION_TXT} - BUILD_TYPE ${CMAKE_BUILD_TYPE} - SHOW_GIT_INFO ${SHOW_GIT_INFO_AND_BUILD_TYPE} - SHOW_BUILD_TYPE ${SHOW_GIT_INFO_AND_BUILD_TYPE} - OUTPUT_VAR WIN32_VERSION_STRING - ) - + # Create binary version number for Win32 integer attributes. + CreateVersionString( + VERSION_TXT ${VERSION_TXT} + OUTPUT_CSV 1 + OUTPUT_VAR WIN32_VERSION_BINARY + ) + + # Create string version number for Win32 detailed attributes. + CreateVersionString( + VERSION_TXT ${VERSION_TXT} + BUILD_TYPE ${CMAKE_BUILD_TYPE} + SHOW_GIT_INFO ${SHOW_GIT_INFO_AND_BUILD_TYPE} + SHOW_BUILD_TYPE ${SHOW_GIT_INFO_AND_BUILD_TYPE} + OUTPUT_VAR WIN32_VERSION_STRING + ) + # Set Win32 icon path. - set(WIN32_ICON_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources/images/game_icon.ico") + set(WIN32_ICON_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources/images/game_icon.ico") configure_file("res/win32/res.rc.template" "${CMAKE_BINARY_DIR}/res.rc" @ONLY) - add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc") - - # Hide console for release configurations. - if (${CMAKE_BUILD_TYPE} MATCHES "Release") - target_link_options(UnleashedRecomp PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup") + add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc") + + # Hide console for release configurations. + if (${CMAKE_BUILD_TYPE} MATCHES "Release") + target_link_options(UnleashedRecomp PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup") endif() else() add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES}) endif() if (UNLEASHED_RECOMP_FLATPAK) - target_compile_definitions(UnleashedRecomp PRIVATE - "UNLEASHED_RECOMP_FLATPAK" - "GAME_INSTALL_DIRECTORY=\"/var/data\"" + target_compile_definitions(UnleashedRecomp PRIVATE + "UNLEASHED_RECOMP_FLATPAK" + "GAME_INSTALL_DIRECTORY=\"/var/data\"" ) endif() @@ -352,9 +352,9 @@ file(CHMOD ${DIRECTX_DXC_TOOL} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) if (WIN32) target_link_libraries(UnleashedRecomp PRIVATE - comctl32 + comctl32 dwmapi - ntdll + ntdll Shcore Synchronization winmm @@ -383,9 +383,12 @@ target_include_directories(UnleashedRecomp PRIVATE ) if (CMAKE_SYSTEM_NAME MATCHES "Linux") + find_package(PkgConfig REQUIRED) find_package(X11 REQUIRED) - target_include_directories(UnleashedRecomp PRIVATE ${X11_INCLUDE_DIR}) - target_link_libraries(UnleashedRecomp PRIVATE ${X11_LIBRARIES}) + pkg_search_module(GLIB REQUIRED glib-2.0) + pkg_search_module(GIO REQUIRED gio-2.0) + target_include_directories(UnleashedRecomp PRIVATE ${X11_INCLUDE_DIR} ${GLIB_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS}) + target_link_libraries(UnleashedRecomp PRIVATE ${X11_LIBRARIES} ${GLIB_LIBRARIES} ${GIO_LIBRARIES}) endif() target_precompile_headers(UnleashedRecomp PUBLIC ${UNLEASHED_RECOMP_PRECOMPILED_HEADERS}) @@ -417,9 +420,9 @@ function(compile_pixel_shader FILE_PATH) compile_shader(${FILE_PATH} ps_6_0) endfunction() -compile_pixel_shader(blend_color_alpha_ps) -compile_vertex_shader(copy_vs) -compile_pixel_shader(copy_color_ps) +compile_pixel_shader(blend_color_alpha_ps) +compile_vertex_shader(copy_vs) +compile_pixel_shader(copy_color_ps) compile_pixel_shader(copy_depth_ps) compile_pixel_shader(csd_filter_ps) compile_vertex_shader(csd_no_tex_vs) @@ -433,7 +436,7 @@ compile_pixel_shader(gamma_correction_ps) compile_pixel_shader(imgui_ps) compile_vertex_shader(imgui_vs) compile_pixel_shader(movie_ps) -compile_vertex_shader(movie_vs) +compile_vertex_shader(movie_vs) compile_pixel_shader(resolve_msaa_color_2x) compile_pixel_shader(resolve_msaa_color_4x) compile_pixel_shader(resolve_msaa_color_8x) @@ -443,7 +446,7 @@ compile_pixel_shader(resolve_msaa_depth_8x) set(RESOURCES_SOURCE_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources") set(RESOURCES_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/res") - + ## Miscellaneous ## BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/bc_diff/button_bc_diff.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/bc_diff/button_bc_diff.bin" ARRAY_NAME "g_button_bc_diff" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.bin" ARRAY_NAME "g_im_font_atlas" COMPRESSION_TYPE "zstd") @@ -455,7 +458,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/co BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/kbm.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/kbm.dds" ARRAY_NAME "g_kbm" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select.dds" ARRAY_NAME "g_select" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/light.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/light.dds" ARRAY_NAME "g_light" COMPRESSION_TYPE "zstd") - + ## Installer ## BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/arrow_circle.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/arrow_circle.dds" ARRAY_NAME "g_arrow_circle" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_001.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_001.dds" ARRAY_NAME "g_install_001" COMPRESSION_TYPE "zstd") @@ -467,23 +470,23 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/in BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_007.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_007.dds" ARRAY_NAME "g_install_007" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_008.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_008.dds" ARRAY_NAME "g_install_008" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/miles_electric_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/miles_electric_icon.dds" ARRAY_NAME "g_miles_electric_icon" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/pulse_install.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/pulse_install.dds" ARRAY_NAME "g_pulse_install" COMPRESSION_TYPE "zstd") - +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/pulse_install.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/pulse_install.dds" ARRAY_NAME "g_pulse_install" COMPRESSION_TYPE "zstd") + ## Options Menu ## BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" ARRAY_NAME "g_achievement_notifications" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input_ps.dds" ARRAY_NAME "g_allow_background_input_ps" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input_xb.dds" ARRAY_NAME "g_allow_background_input_xb" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" ARRAY_NAME "g_antialiasing_none" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" ARRAY_NAME "g_antialiasing_2x" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" ARRAY_NAME "g_antialiasing_4x" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" ARRAY_NAME "g_antialiasing_none" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" ARRAY_NAME "g_antialiasing_2x" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" ARRAY_NAME "g_antialiasing_4x" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_8x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_8x.dds" ARRAY_NAME "g_antialiasing_8x" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/aspect_ratio.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/aspect_ratio.dds" ARRAY_NAME "g_aspect_ratio" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/battle_theme.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/battle_theme.dds" ARRAY_NAME "g_battle_theme" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/brightness.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/brightness.dds" ARRAY_NAME "g_brightness" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_stereo.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_stereo.dds" ARRAY_NAME "g_channel_stereo" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_surround.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_surround.dds" ARRAY_NAME "g_channel_surround" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/brightness.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/brightness.dds" ARRAY_NAME "g_brightness" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_stereo.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_stereo.dds" ARRAY_NAME "g_channel_stereo" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_surround.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_surround.dds" ARRAY_NAME "g_channel_surround" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial_ps.dds" ARRAY_NAME "g_control_tutorial_ps" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" ARRAY_NAME "g_control_tutorial_xb" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" ARRAY_NAME "g_control_tutorial_xb" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/controller_icons.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/controller_icons.dds" ARRAY_NAME "g_controller_icons" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/default.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/default.dds" ARRAY_NAME "g_default" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/effects_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/effects_volume.dds" ARRAY_NAME "g_effects_volume" COMPRESSION_TYPE "zstd") @@ -499,7 +502,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/op BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_off.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_off.dds" ARRAY_NAME "g_motion_blur_off" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_original.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_original.dds" ARRAY_NAME "g_motion_blur_original" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_enhanced.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_enhanced.dds" ARRAY_NAME "g_motion_blur_enhanced" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" ARRAY_NAME "g_movie_scale_fit" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" ARRAY_NAME "g_movie_scale_fit" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_fill.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_fill.dds" ARRAY_NAME "g_movie_scale_fill" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_attenuation.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_attenuation.dds" ARRAY_NAME "g_music_attenuation" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_volume.dds" ARRAY_NAME "g_music_volume" COMPRESSION_TYPE "zstd") @@ -508,34 +511,34 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/op BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" ARRAY_NAME "g_shadow_resolution_x2048" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" ARRAY_NAME "g_shadow_resolution_x4096" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" ARRAY_NAME "g_shadow_resolution_x8192" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_transition_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_transition_ps.dds" ARRAY_NAME "g_time_of_day_transition_playstation" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_transition_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_transition_ps.dds" ARRAY_NAME "g_time_of_day_transition_playstation" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_transition_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_transition_xb.dds" ARRAY_NAME "g_time_of_day_transition_xbox" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" ARRAY_NAME "g_transparency_antialiasing_false" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" ARRAY_NAME "g_transparency_antialiasing_true" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" ARRAY_NAME "g_ui_alignment_centre" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" ARRAY_NAME "g_ui_alignment_centre" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_alignment_edge.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_alignment_edge.dds" ARRAY_NAME "g_ui_alignment_edge" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vertical_camera.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vertical_camera.dds" ARRAY_NAME "g_vertical_camera" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/voice_language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/voice_language.dds" ARRAY_NAME "g_voice_language" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration_ps.dds" ARRAY_NAME "g_vibration_ps" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration_xb.dds" ARRAY_NAME "g_vibration_xb" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync_on.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync_on.dds" ARRAY_NAME "g_vsync_on" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration_xb.dds" ARRAY_NAME "g_vibration_xb" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync_on.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync_on.dds" ARRAY_NAME "g_vsync_on" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync_off.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync_off.dds" ARRAY_NAME "g_vsync_off" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/window_size.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/window_size.dds" ARRAY_NAME "g_window_size" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/xbox_color_correction.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/xbox_color_correction.dds" ARRAY_NAME "g_xbox_color_correction" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/miles_electric.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/miles_electric.dds" ARRAY_NAME "g_miles_electric" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/options_static.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/options_static.dds" ARRAY_NAME "g_options_static" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/miles_electric.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/miles_electric.dds" ARRAY_NAME "g_miles_electric" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/options_static.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/options_static.dds" ARRAY_NAME "g_options_static" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/options_static_flash.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/options_static_flash.dds" ARRAY_NAME "g_options_static_flash" COMPRESSION_TYPE "zstd") - + ## Game Icon ## BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon.bmp" ARRAY_NAME "g_game_icon") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon_night.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon_night.bmp" ARRAY_NAME "g_game_icon_night") - +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon_night.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon_night.bmp" ARRAY_NAME "g_game_icon_night") + ## Audio ## -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/music/installer.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/music/installer.ogg" ARRAY_NAME "g_installer_music") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/music/installer.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/music/installer.ogg" ARRAY_NAME "g_installer_music") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_worldmap_cursor.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_worldmap_cursor.ogg" ARRAY_NAME "g_sys_worldmap_cursor") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_worldmap_finaldecide.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_worldmap_finaldecide.ogg" ARRAY_NAME "g_sys_worldmap_finaldecide") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausecansel.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausecansel.ogg" ARRAY_NAME "g_sys_actstg_pausecansel") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausecursor.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausecursor.ogg" ARRAY_NAME "g_sys_actstg_pausecursor") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausedecide.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausedecide.ogg" ARRAY_NAME "g_sys_actstg_pausedecide") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinclose.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinclose.ogg" ARRAY_NAME "g_sys_actstg_pausewinclose") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinopen.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinopen.ogg" ARRAY_NAME "g_sys_actstg_pausewinopen") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinopen.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinopen.ogg" ARRAY_NAME "g_sys_actstg_pausewinopen") diff --git a/UnleashedRecomp/os/linux/media_linux.cpp b/UnleashedRecomp/os/linux/media_linux.cpp index 9fc19b0..45a29ea 100644 --- a/UnleashedRecomp/os/linux/media_linux.cpp +++ b/UnleashedRecomp/os/linux/media_linux.cpp @@ -1,7 +1,389 @@ +#include +#include +#include +#include +#include +#include +#include +#include #include +#include + +enum class PlaybackStatus +{ + Stopped, + Playing, + Paused +}; + +static const char* DBusInterface = "org.freedesktop.DBus"; +static const char* DBusPropertiesInterface = "org.freedesktop.DBus.Properties"; +static const char* DBusPath = "/org/freedesktop/DBus"; +static const char* MPRIS2Interface = "org.mpris.MediaPlayer2"; +static const char* MPRIS2PlayerInterface = "org.mpris.MediaPlayer2.Player"; +static const char* MPRIS2Path = "/org/mpris/MediaPlayer2"; +static const char* MPRIS2PlayerctldBus = "org.mpris.MediaPlayer2.playerctld"; + +static std::optional g_dbusThread; +static std::string g_playerctldBus; +static std::unordered_map g_playerStatus; +static std::list g_activePlayers; +static std::atomic g_activeStatus; + +static PlaybackStatus PlaybackStatusFromString(const char* str) +{ + if (g_str_equal(str, "Playing")) + return PlaybackStatus::Playing; + else if (g_str_equal(str, "Paused")) + return PlaybackStatus::Paused; + else + return PlaybackStatus::Stopped; +} + +static bool ContainerHas(const auto& container, const auto& value) +{ + return std::find(container.begin(), container.end(), value) != container.end(); +} + +static void UpdateActiveStatus() +{ + if (!g_activePlayers.empty()) + g_activeStatus = g_playerStatus[g_activePlayers.front()]; + else + g_activeStatus = PlaybackStatus::Stopped; +} + +static void UpdateActivePlayers(const char* name, PlaybackStatus status) +{ + if (status == PlaybackStatus::Stopped) + { + // Don't remove playerctld from the queue, we want to prefer it for as long as it's available + if (!g_str_equal(name, g_playerctldBus.c_str())) + { + g_activePlayers.remove(name); + } + } + else if (!ContainerHas(g_activePlayers, name)) + { + // Prioritise playerctld if and when it appears + if (g_str_equal(name, g_playerctldBus.c_str())) + { + g_activePlayers.emplace_front(name); + } + else + { + g_activePlayers.emplace_back(name); + } + } + + g_playerStatus.insert_or_assign(name, status); + UpdateActiveStatus(); +} + +static PlaybackStatus MPRISGetPlaybackStatus(GDBusConnection* connection, const gchar* name) +{ + GError* error; + GVariant* response; + GVariant* tupleChild; + GVariant* value; + PlaybackStatus status; + + error = NULL; + + response = g_dbus_connection_call_sync( + connection, + name, + MPRIS2Path, + DBusPropertiesInterface, + "Get", + g_variant_new("(ss)", MPRIS2PlayerInterface, "PlaybackStatus"), + G_VARIANT_TYPE("(v)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error + ); + + if (!response) + { + LOGF_ERROR("Failed to process D-Bus Get: {}", error->message); + g_clear_error(&error); + return PlaybackStatus::Stopped; + } + + tupleChild = g_variant_get_child_value(response, 0); + value = g_variant_get_variant(tupleChild); + + if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) + { + LOG_ERROR("Failed to process D-Bus Get"); + g_variant_unref(tupleChild); + return PlaybackStatus::Stopped; + } + + status = PlaybackStatusFromString(g_variant_get_string(value, NULL)); + + g_variant_unref(value); + g_variant_unref(tupleChild); + g_variant_unref(response); + + return status; +} + +// Something is very wrong with the system if this happens +static void DBusConnectionClosed(GDBusConnection* connection, + gboolean remotePeerVanished, + GError* error, + gpointer userData) +{ + LOG_ERROR("D-Bus connection closed"); + g_activeStatus = PlaybackStatus::Stopped; + g_main_loop_quit((GMainLoop*)userData); +} + +static void DBusNameOwnerChanged(GDBusConnection* connection, + const gchar* senderName, + const gchar* objectPath, + const gchar* interfaceName, + const gchar* signalName, + GVariant* parameters, + gpointer userData) +{ + const char* name; + const char* oldOwner; + const char* newOwner; + + g_variant_get(parameters, "(&s&s&s)", &name, &oldOwner, &newOwner); + + if (g_str_has_prefix(name, MPRIS2Interface)) + { + if (g_str_equal(name, MPRIS2PlayerctldBus)) + { + g_playerctldBus = newOwner; + } + + if (oldOwner[0]) + { + g_playerStatus.erase(oldOwner); + g_activePlayers.remove(oldOwner); + } + + UpdateActiveStatus(); + } +} + +static void MPRISPropertiesChanged(GDBusConnection* connection, + const gchar* senderName, + const gchar* objectPath, + const gchar* interfaceName, + const gchar* signalName, + GVariant* parameters, + gpointer userData) +{ + const char* interface; + GVariant* changed; + GVariantIter iter; + const char* key; + GVariant* value; + PlaybackStatus playbackStatus; + + g_variant_get_child(parameters, 0, "&s", &interface); + g_variant_get_child(parameters, 1, "@a{sv}", &changed); + + g_variant_iter_init(&iter, changed); + while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) + { + if (g_str_equal(key, "PlaybackStatus")) + { + playbackStatus = PlaybackStatusFromString(g_variant_get_string(value, NULL)); + UpdateActivePlayers(senderName, playbackStatus); + g_variant_unref(value); + break; + } + g_variant_unref(value); + } + + g_variant_unref(changed); +} + +/* Called upon connect to discover already active MPRIS2 players by looking for + well-known bus names that begin with the MPRIS2 path. + We determine what their priority would be when pushed to the player queue + based on their current status. + The queue (and accompanying data structures) stores unique connection names, + not their well-known ones, as the PropertiesChanged signal only provides the + former. */ +static void DBusListNamesReceived(GObject* object, GAsyncResult* res, gpointer userData) +{ + GDBusConnection* connection; + GError* error; + GVariant* response; + GVariant* tupleChild; + GVariantIter iter; + const gchar* name; + bool foundPlayerctld; + std::list pausedPlayers; + + connection = G_DBUS_CONNECTION(object); + error = NULL; + response = g_dbus_connection_call_finish(connection, res, &error); + foundPlayerctld = false; + + if (!response) + { + LOGF_ERROR("Failed to process D-Bus ListNames: {}", error->message); + g_clear_error(&error); + return; + } + + tupleChild = g_variant_get_child_value(response, 0); + + g_variant_iter_init(&iter, tupleChild); + while (g_variant_iter_next(&iter, "&s", &name)) + { + GVariant* ownerResponse; + const gchar* ownerName; + PlaybackStatus status; + + if (!g_str_has_prefix(name, MPRIS2Interface)) + continue; + + ownerResponse = g_dbus_connection_call_sync( + connection, + DBusInterface, + DBusPath, + DBusInterface, + "GetNameOwner", + g_variant_new("(s)", name), + G_VARIANT_TYPE("(s)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error + ); + + if (!ownerResponse) + { + LOGF_ERROR("Failed to process D-Bus GetNameOwner: {}", error->message); + g_clear_error(&error); + g_variant_unref(tupleChild); + g_variant_unref(response); + return; + } + + g_variant_get(ownerResponse, "(&s)", &ownerName); + status = MPRISGetPlaybackStatus(connection, ownerName); + + // Prioritise playerctld, even if current playback status is stopped + if (!foundPlayerctld && g_str_equal(name, MPRIS2PlayerctldBus)) + { + foundPlayerctld = true; + g_playerctldBus = ownerName; + g_activePlayers.emplace_front(ownerName); + } + else if (status != PlaybackStatus::Stopped) + { + if (status == PlaybackStatus::Playing) + { + g_activePlayers.emplace_back(ownerName); + } + else + { + pausedPlayers.emplace_back(ownerName); + } + } + + g_playerStatus.insert_or_assign(ownerName, status); + g_variant_unref(ownerResponse); + } + + // Put all the paused players at the end of the queue + g_activePlayers.splice(g_activePlayers.end(), pausedPlayers); + UpdateActiveStatus(); + + g_variant_unref(tupleChild); + g_variant_unref(response); +} + +static void DBusThreadProc() +{ + GMainContext* mainContext; + GMainLoop* mainLoop; + GError* error; + GDBusConnection* connection; + + mainContext = g_main_context_new(); + g_main_context_push_thread_default(mainContext); + mainLoop = g_main_loop_new(mainContext, FALSE); + error = NULL; + + connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); + if (!connection) + { + LOGF_ERROR("Failed to connect to D-Bus: {}", error->message); + g_clear_error(&error); + g_main_context_unref(mainContext); + g_main_loop_unref(mainLoop); + return; + } + + g_dbus_connection_set_exit_on_close(connection, FALSE); + g_signal_connect(connection, "closed", G_CALLBACK(DBusConnectionClosed), mainLoop); + + // Listen for player connection changes + g_dbus_connection_signal_subscribe( + connection, + DBusInterface, + DBusInterface, + "NameOwnerChanged", + DBusPath, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + DBusNameOwnerChanged, + NULL, + NULL + ); + + // Listen for player status changes + g_dbus_connection_signal_subscribe( + connection, + NULL, + DBusPropertiesInterface, + "PropertiesChanged", + MPRIS2Path, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + MPRISPropertiesChanged, + NULL, + NULL + ); + + // Request list of current players + g_dbus_connection_call( + connection, + DBusInterface, + DBusPath, + DBusInterface, + "ListNames", + NULL, + G_VARIANT_TYPE("(as)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + DBusListNamesReceived, + NULL + ); + + g_main_loop_run(mainLoop); +} bool os::media::IsExternalMediaPlaying() { - // This functionality is not supported in Linux. - return false; + if (!g_dbusThread) + { + g_dbusThread.emplace(DBusThreadProc); + g_dbusThread->detach(); + } + + return g_activeStatus == PlaybackStatus::Playing; } diff --git a/UnleashedRecomp/patches/audio_patches.cpp b/UnleashedRecomp/patches/audio_patches.cpp index 749d1c6..5f5603d 100644 --- a/UnleashedRecomp/patches/audio_patches.cpp +++ b/UnleashedRecomp/patches/audio_patches.cpp @@ -29,6 +29,8 @@ bool AudioPatches::CanAttenuate() m_isAttenuationSupported = version.Major >= 10 && version.Build >= 17763; return m_isAttenuationSupported; +#elif __linux__ + return true; #else return false; #endif