diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index 10863c02..4b4c78c0 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -386,6 +386,17 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") find_package(X11 REQUIRED) target_include_directories(UnleashedRecomp PRIVATE ${X11_INCLUDE_DIR}) target_link_libraries(UnleashedRecomp PRIVATE ${X11_LIBRARIES}) + + find_package(PkgConfig) + pkg_check_modules(GIO gio-2.0) + + if(GIO_FOUND) + add_compile_definitions(FOUND_GIO) + target_include_directories(UnleashedRecomp PRIVATE ${GIO_INCLUDE_DIRS}) + target_link_libraries(UnleashedRecomp PRIVATE ${GIO_LIBRARIES}) + else() + message(FATAL_ERROR "GIO not found") + endif() endif() target_precompile_headers(UnleashedRecomp PUBLIC ${UNLEASHED_RECOMP_PRECOMPILED_HEADERS}) diff --git a/UnleashedRecomp/os/linux/media_linux.cpp b/UnleashedRecomp/os/linux/media_linux.cpp index 9fc19b0a..2df9f44a 100644 --- a/UnleashedRecomp/os/linux/media_linux.cpp +++ b/UnleashedRecomp/os/linux/media_linux.cpp @@ -1,7 +1,89 @@ +#ifdef FOUND_GIO +#include +#endif #include +#include +#include +#include +#include -bool os::media::IsExternalMediaPlaying() -{ - // This functionality is not supported in Linux. - return false; +#ifdef FOUND_GIO +static std::vector get_mpris_nams(GDBusConnection *connection, + GError *error) { + std::vector names; + + GVariant *result = g_dbus_connection_call_sync( + connection, + "org.freedesktop.DBus", // destination + "/org/freedesktop/DBus", // object path + "org.freedesktop.DBus", // interface + "ListNames", // method + NULL, // parameters + G_VARIANT_TYPE("(as)"), // expected return type + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + + if (!result) { + g_printerr("Failed to list names: %s\n", error->message); + g_error_free(error); + return {}; + } + + // Extract an array of names + GVariantIter *iter; + const gchar *name; + g_variant_get(result, "(as)", &iter); + while (g_variant_iter_loop(iter, "s", &name)) { + if (g_str_has_prefix(name, "org.mpris.MediaPlayer2.")) { + names.push_back(name); + } + } + + g_variant_iter_free(iter); + g_variant_unref(result); + return names; +} +#endif + +bool os::media::IsExternalMediaPlaying() { + #ifdef FOUND_GIO + GDBusConnection *connection; + GError *error = NULL; + + // Connect to the session bus + connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); + if (!connection) { + g_printerr("Failed to connect to session bus: %s\n", error->message); + g_error_free(error); + return false; + } + + auto names = get_mpris_nams(connection, error); + bool found = false; + for (auto name : names) { + GVariant *prop_result = g_dbus_connection_call_sync( + connection, name.c_str(), "/org/mpris/MediaPlayer2", + "org.freedesktop.DBus.Properties", "Get", + g_variant_new("(ss)", "org.mpris.MediaPlayer2.Player", + "PlaybackStatus"), + G_VARIANT_TYPE("(v)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + + if (!prop_result) { + g_clear_error(&error); + continue; + } + + GVariant *variant; + g_variant_get(prop_result, "(v)", &variant); + const gchar *playback_status = g_variant_get_string(variant, NULL); + std::string status(playback_status); + found = found or (status.find("Playing") != std::string::npos); + + g_variant_unref(variant); + g_variant_unref(prop_result); + } + g_object_unref(connection); + return found; + #else + return false; + #endif } diff --git a/UnleashedRecomp/patches/audio_patches.cpp b/UnleashedRecomp/patches/audio_patches.cpp index 749d1c69..56623218 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 defined(FOUND_GIO) + return true; #else return false; #endif