mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-04-28 13:27:58 +03:00
Implement music attenuation on Linux
This is implemented by listening for event changes from MPRIS2 clients over D-Bus. Unfortunately there is no good API for this nor a good way to identify current player as there is on Windows, and as such we have to track and queue them manually just to get a seemingly good enough result. This also gives us the issue of needing to guess and manually prioritise which player to use when we first start, as we cannot determine when something before us started. playerctld is preferred to be read on systems that have it available, however that has the behaviour of setting its status to the most recent change. Those who use this and have media key scripts use it would likely be expecting such behaviour though. (All my editors were eager to fix inconsistent CRLF's in the CMakeLists, sorry)
This commit is contained in:
parent
e4c43ae3b1
commit
8baa6d2a20
3 changed files with 455 additions and 68 deletions
|
@ -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")
|
||||
|
|
|
@ -1,7 +1,389 @@
|
|||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <gio/gio.h>
|
||||
#include <os/media.h>
|
||||
#include <os/logger.h>
|
||||
|
||||
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<std::thread> g_dbusThread;
|
||||
static std::string g_playerctldBus;
|
||||
static std::unordered_map<std::string, PlaybackStatus> g_playerStatus;
|
||||
static std::list<std::string> g_activePlayers;
|
||||
static std::atomic<PlaybackStatus> 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<std::string> 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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue