diff --git a/cmake/packaging/windows.cmake b/cmake/packaging/windows.cmake index 1f4785cff4d..9885a1d36b5 100644 --- a/cmake/packaging/windows.cmake +++ b/cmake/packaging/windows.cmake @@ -37,6 +37,9 @@ install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/gamepad/" install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/vdd/" DESTINATION "scripts" COMPONENT vdd) +install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/misc/cmd/" + DESTINATION "tools" + COMPONENT superCmds) # Sunshine assets install(DIRECTORY "${SUNSHINE_SOURCE_ASSETS_DIR}/windows/assets/" diff --git a/src/config.cpp b/src/config.cpp index 3e6ac5ee3b5..afa7a9cc54e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -979,6 +979,14 @@ namespace config { return opts; } + void + sync_idd_f(std::unordered_map &vars, const std::string &name, std::string &input) { + std::string idd_adapter_path = "c:\\IddSampleDriver\\adapter.txt"; // "C:\IddSampleDriver\adapter.txt" + if (fs::exists(idd_adapter_path) && !input.empty()) { + file_handler::write_file(idd_adapter_path.c_str(), input.c_str()); + } + } + void apply_config(std::unordered_map &&vars) { if (!fs::exists(stream.file_apps.c_str())) { @@ -1059,6 +1067,7 @@ namespace config { string_f(vars, "capture", video.capture); string_f(vars, "encoder", video.encoder); string_f(vars, "adapter_name", video.adapter_name); + sync_idd_f(vars, "adapter_name", video.adapter_name); string_f(vars, "output_name", video.output_name); int_f(vars, "display_device_prep", video.display_device_prep, display_device::parsed_config_t::device_prep_from_view); diff --git a/src/confighttp.cpp b/src/confighttp.cpp index c1f2555d61e..7211fb6818e 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -550,7 +550,6 @@ namespace confighttp { }); auto devices { display_device::enum_available_devices() }; - pt::ptree devices_nodes; for (const auto &[device_id, data] : devices) { pt::ptree devices_node; @@ -559,7 +558,16 @@ namespace confighttp { devices_nodes.push_back(std::make_pair(""s, devices_node)); } + auto adapters { platf::adapter_names() }; + pt::ptree adapters_nodes; + for (const auto &adapter_name : adapters) { + pt::ptree adapters_node; + adapters_node.put("name"s, adapter_name); + adapters_nodes.push_back(std::make_pair(""s, adapters_node)); + } + outputTree.add_child("display_devices", devices_nodes); + outputTree.add_child("adapters", adapters_nodes); outputTree.put("status", "true"); outputTree.put("platform", SUNSHINE_PLATFORM); outputTree.put("version", PROJECT_VER); diff --git a/src/display_device/session.cpp b/src/display_device/session.cpp index c1cf38dba1b..9fb9db93f81 100644 --- a/src/display_device/session.cpp +++ b/src/display_device/session.cpp @@ -1,9 +1,11 @@ // standard includes #include +#include // local includes #include "session.h" #include "src/platform/common.h" +#include "src/platform/windows/display_device/windows_utils.h" #include "to_string.h" namespace display_device { @@ -204,6 +206,21 @@ namespace display_device { } else { if (settings.is_changing_settings_going_to_fail()) { + // display_device::w_utils::togglePnpDeviceByFriendlyName("Virtual Display with HDR", false); + // BOOST_LOG(info) << "Disable IDD..."; + boost::process::environment _env = boost::this_process::environment(); + auto working_dir = boost::filesystem::path(); + std::error_code ec; + std::string cmd = "C:\\Program Files\\Sunshine\\tools\\device-toggler.exe 2 2 \"Virtual Display with HDR\""; + + auto child = platf::run_command(true, true, cmd, working_dir, _env, nullptr, ec, nullptr); + if (ec) { + BOOST_LOG(warning) << "Couldn't run cmd ["sv << cmd << "]: System: "sv << ec.message(); + } + else { + BOOST_LOG(info) << "Executing idd cmd ["sv << cmd << "]"sv; + child.detach(); + } BOOST_LOG(warning) << "Reverting display settings will fail - retrying later..."; } @@ -213,6 +230,23 @@ namespace display_device { return false; } + boost::process::environment _env = boost::this_process::environment(); + auto working_dir = boost::filesystem::path(); + std::error_code ec; + std::string cmd = "C:\\Program Files\\Sunshine\\tools\\device-toggler.exe 1 2 \"Virtual Display with HDR\""; + + auto child = platf::run_command(true, true, cmd, working_dir, _env, nullptr, ec, nullptr); + if (ec) { + BOOST_LOG(warning) << "Couldn't run cmd ["sv << cmd << "]: System: "sv << ec.message(); + } + else { + BOOST_LOG(info) << "Executing idd cmd ["sv << cmd << "]"sv; + child.detach(); + } + + // display_device::w_utils::togglePnpDeviceByFriendlyName("Generic Monitor (IDD HDR)", true); + // BOOST_LOG(info) << "Enable IDD..."; + Sleep(1000); return settings.revert_settings(); }); } diff --git a/src/entry_handler.cpp b/src/entry_handler.cpp index fb1ece2ca39..f8dcba27ac7 100644 --- a/src/entry_handler.cpp +++ b/src/entry_handler.cpp @@ -7,6 +7,8 @@ #include #include +#include + // local includes #include "config.h" #include "confighttp.h" @@ -16,6 +18,8 @@ #include "logging.h" #include "network.h" #include "platform/common.h" +#include "src/display_device/display_device.h" +#include "src/platform/windows/display_device/windows_utils.h" #include "version.h" extern "C" { @@ -84,6 +88,26 @@ namespace lifetime { int zero = 0; desired_exit_code.compare_exchange_strong(zero, exit_code); +#ifdef _WIN32 + if (async) { + // boost::process::environment _env = boost::this_process::environment(); + // auto working_dir = boost::filesystem::path(); + // std::error_code ec; + // std::string cmd = "C:\\Program Files\\Sunshine\\tools\\device-toggler.exe 2 \"Virtual Display with HDR\""; + + // auto child = platf::run_command(true, true, cmd, working_dir, _env, nullptr, ec, nullptr); + // if (ec) { + // BOOST_LOG(warning) << "Couldn't run cmd ["sv << cmd << "]: System: "sv << ec.message(); + // } + // else { + // BOOST_LOG(info) << "Executing sleep cmd ["sv << cmd << "]"sv; + // child.detach(); + // } + // display_device::w_utils::togglePnpDeviceByFriendlyName("Generic Monitor (IDD HDR)", false); + // BOOST_LOG(info) << "Disable Generic Monitor (IDD HDR)..."; + } +#endif + // Raise SIGINT to start termination std::raise(SIGINT); diff --git a/src/platform/common.h b/src/platform/common.h index 24cd658b04d..8db3f3e7354 100644 --- a/src/platform/common.h +++ b/src/platform/common.h @@ -578,6 +578,9 @@ namespace platf { std::vector display_names(mem_type_e hwdevice_type); + std::vector + adapter_names(); + /** * @brief Check if GPUs/drivers have changed since the last call to this function. * @return `true` if a change has occurred or if it is unknown whether a change occurred. diff --git a/src/platform/windows/display_base.cpp b/src/platform/windows/display_base.cpp index a0f6e93efb9..619e9a99810 100644 --- a/src/platform/windows/display_base.cpp +++ b/src/platform/windows/display_base.cpp @@ -1146,6 +1146,33 @@ namespace platf { return display_names; } + + std::vector + adapter_names() { + std::vector adapter_names; + + HRESULT status; + + dxgi::factory1_t factory; + status = CreateDXGIFactory1(IID_IDXGIFactory1, (void **) &factory); + if (FAILED(status)) { + BOOST_LOG(error) << "Failed to create DXGIFactory1 [0x"sv << util::hex(status).to_string_view() << ']'; + return {}; + } + + dxgi::adapter_t adapter; + for (int x = 0; factory->EnumAdapters1(x, &adapter) != DXGI_ERROR_NOT_FOUND; ++x) { + DXGI_ADAPTER_DESC1 adapter_desc; + adapter->GetDesc1(&adapter_desc); + + auto adapter_name = to_utf8(adapter_desc.Description); + adapter_names.emplace_back(std::move(adapter_name)); + } + + return adapter_names; + } + + /** * @brief Returns if GPUs/drivers have changed since the last call to this function. * @return `true` if a change has occurred or if it is unknown whether a change occurred. diff --git a/src/platform/windows/display_device/windows_utils.cpp b/src/platform/windows/display_device/windows_utils.cpp index 176c8a7b7fa..cad5978526c 100644 --- a/src/platform/windows/display_device/windows_utils.cpp +++ b/src/platform/windows/display_device/windows_utils.cpp @@ -651,4 +651,50 @@ namespace display_device::w_utils { return result == ERROR_ACCESS_DENIED; } + bool + togglePnpDeviceByFriendlyName(const std::string &friendlyName, const bool &stat) { + HDEVINFO deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES); + if (deviceInfoSet == INVALID_HANDLE_VALUE) { + std::cerr << "Failed to get device information set." << std::endl; + return false; + } + + SP_DEVINFO_DATA deviceInfoData; + deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + bool deviceFound = false; + for (DWORD i = 0; SetupDiEnumDeviceInfo(deviceInfoSet, i, &deviceInfoData); ++i) { + TCHAR deviceFriendlyName[256]; + if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE) deviceFriendlyName, sizeof(deviceFriendlyName), NULL)) { + if (friendlyName == deviceFriendlyName) { + deviceFound = true; + break; + } + } + } + + if (!deviceFound) { + std::cerr << "Device not found." << std::endl; + SetupDiDestroyDeviceInfoList(deviceInfoSet); + return false; + } + + SP_PROPCHANGE_PARAMS propChangeParams; + propChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + propChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; + propChangeParams.StateChange = stat ? DICS_ENABLE : DICS_DISABLE; + propChangeParams.Scope = DICS_FLAG_GLOBAL; + propChangeParams.HwProfile = 0; + + if (!SetupDiSetClassInstallParams(deviceInfoSet, &deviceInfoData, &propChangeParams.ClassInstallHeader, sizeof(propChangeParams)) || + !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, deviceInfoSet, &deviceInfoData)) { + std::cerr << "Failed to toggle device." << std::endl; + SetupDiDestroyDeviceInfoList(deviceInfoSet); + return false; + } + + SetupDiDestroyDeviceInfoList(deviceInfoSet); + return true; + } + } // namespace display_device::w_utils diff --git a/src/platform/windows/display_device/windows_utils.h b/src/platform/windows/display_device/windows_utils.h index 78843a8ad8c..fb86e318c3e 100644 --- a/src/platform/windows/display_device/windows_utils.h +++ b/src/platform/windows/display_device/windows_utils.h @@ -488,4 +488,6 @@ namespace display_device::w_utils { bool test_no_access_to_ccd_api(); + bool + togglePnpDeviceByFriendlyName(const std::string &friendlyName, const bool &stat); } // namespace display_device::w_utils diff --git a/src/system_tray.cpp b/src/system_tray.cpp index 01160a61c2d..4574da9abcb 100644 --- a/src/system_tray.cpp +++ b/src/system_tray.cpp @@ -91,7 +91,7 @@ namespace system_tray { int msgboxID = MessageBoxW( NULL, L"你不能退出!\n那么想退吗? 真拿你没办法呢, 继续点一下吧~", - L"退你妹", + L"真的要退出吗", MB_ICONWARNING | MB_OKCANCEL); if (msgboxID == IDOK) { diff --git a/src_assets/common/assets/web/configs/tabs/audiovideo/AdapterNameSelector.vue b/src_assets/common/assets/web/configs/tabs/audiovideo/AdapterNameSelector.vue index 8fa94ce8b05..79b6db6cbad 100644 --- a/src_assets/common/assets/web/configs/tabs/audiovideo/AdapterNameSelector.vue +++ b/src_assets/common/assets/web/configs/tabs/audiovideo/AdapterNameSelector.vue @@ -14,14 +14,26 @@ const config = ref(props.config)