mirror of
https://github.com/thinkonmay/sunshine-sdk.git
synced 2025-12-31 19:45:40 +00:00
Add support for installing the Steam Streaming Speakers driver (#1262)
Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com>
This commit is contained in:
parent
4ae412b219
commit
53125ffeca
@ -483,7 +483,8 @@ virtual_sink
|
||||
|
||||
- Stream Streaming Speakers (Linux, macOS, Windows)
|
||||
|
||||
- To use this option, you must have Steam installed and have used Stream remote play at least once.
|
||||
- Steam must be installed.
|
||||
- Enable `install_steam_audio_drivers`_ or use Steam Remote Play at least once to install the drivers.
|
||||
|
||||
- `Virtual Audio Cable <https://vb-audio.com/Cable/>`_ (macOS, Windows)
|
||||
|
||||
@ -492,6 +493,22 @@ virtual_sink
|
||||
|
||||
virtual_sink = Steam Streaming Speakers
|
||||
|
||||
install_steam_audio_drivers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
**Description**
|
||||
Installs the Steam Streaming Speakers driver (if Steam is installed) to support surround sound and muting host audio.
|
||||
|
||||
.. Tip:: This option is only supported on Windows.
|
||||
|
||||
**Default**
|
||||
``enabled``
|
||||
|
||||
**Example**
|
||||
.. code-block:: text
|
||||
|
||||
install_steam_audio_drivers = enabled
|
||||
|
||||
Network
|
||||
-------
|
||||
|
||||
|
||||
@ -382,7 +382,11 @@ namespace config {
|
||||
true // dwmflush
|
||||
};
|
||||
|
||||
audio_t audio {};
|
||||
audio_t audio {
|
||||
{}, // audio_sink
|
||||
{}, // virtual_sink
|
||||
true, // install_steam_drivers
|
||||
};
|
||||
|
||||
stream_t stream {
|
||||
10s, // ping_timeout
|
||||
@ -985,6 +989,7 @@ namespace config {
|
||||
|
||||
string_f(vars, "audio_sink", audio.sink);
|
||||
string_f(vars, "virtual_sink", audio.virtual_sink);
|
||||
bool_f(vars, "install_steam_audio_drivers", audio.install_steam_drivers);
|
||||
|
||||
string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, { "pc"sv, "lan"sv, "wan"sv });
|
||||
string_restricted_f(vars, "origin_web_ui_allowed", nvhttp.origin_web_ui_allowed, { "pc"sv, "lan"sv, "wan"sv });
|
||||
|
||||
@ -65,6 +65,7 @@ namespace config {
|
||||
struct audio_t {
|
||||
std::string sink;
|
||||
std::string virtual_sink;
|
||||
bool install_steam_drivers;
|
||||
};
|
||||
|
||||
struct stream_t {
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
|
||||
#include <synchapi.h>
|
||||
|
||||
#include <newdev.h>
|
||||
|
||||
#define INITGUID
|
||||
#include <propkeydef.h>
|
||||
#undef INITGUID
|
||||
@ -32,10 +34,20 @@ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
|
||||
const IID IID_IAudioClient = __uuidof(IAudioClient);
|
||||
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
|
||||
|
||||
#if defined(__x86_64) || defined(_M_AMD64)
|
||||
#define STEAM_DRIVER_SUBDIR L"x64"
|
||||
#elif defined(__i386) || defined(_M_IX86)
|
||||
#define STEAM_DRIVER_SUBDIR L"x86"
|
||||
#else
|
||||
#warning No known Steam audio driver for this architecture
|
||||
#endif
|
||||
|
||||
using namespace std::literals;
|
||||
namespace platf::audio {
|
||||
constexpr auto SAMPLE_RATE = 48000;
|
||||
|
||||
constexpr auto STEAM_AUDIO_DRIVER_PATH = L"%CommonProgramFiles(x86)%\\Steam\\drivers\\Windows10\\" STEAM_DRIVER_SUBDIR L"\\SteamStreamingSpeakers.inf";
|
||||
|
||||
template <class T>
|
||||
void
|
||||
Release(T *p) {
|
||||
@ -254,7 +266,7 @@ namespace platf::audio {
|
||||
&device);
|
||||
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Couldn't create audio Device [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
BOOST_LOG(error) << "Couldn't get default audio endpoint [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -577,20 +589,6 @@ namespace platf::audio {
|
||||
|
||||
sink_t sink;
|
||||
|
||||
audio::device_enum_t device_enum;
|
||||
auto status = CoCreateInstance(
|
||||
CLSID_MMDeviceEnumerator,
|
||||
nullptr,
|
||||
CLSCTX_ALL,
|
||||
IID_IMMDeviceEnumerator,
|
||||
(void **) &device_enum);
|
||||
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Couldn't create Device Enumerator: [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto device = default_device(device_enum);
|
||||
if (!device) {
|
||||
return std::nullopt;
|
||||
@ -602,7 +600,7 @@ namespace platf::audio {
|
||||
sink.host = converter.to_bytes(wstring.get());
|
||||
|
||||
collection_t collection;
|
||||
status = device_enum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection);
|
||||
auto status = device_enum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection);
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Couldn't enumerate: [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
|
||||
@ -814,22 +812,8 @@ namespace platf::audio {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
audio::device_enum_t device_enum;
|
||||
auto status = CoCreateInstance(
|
||||
CLSID_MMDeviceEnumerator,
|
||||
nullptr,
|
||||
CLSCTX_ALL,
|
||||
IID_IMMDeviceEnumerator,
|
||||
(void **) &device_enum);
|
||||
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Couldn't create Device Enumerator: [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
collection_t collection;
|
||||
status = device_enum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection);
|
||||
auto status = device_enum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection);
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Couldn't enumerate: [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
|
||||
@ -878,6 +862,79 @@ namespace platf::audio {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Installs the Steam Streaming Speakers driver, if present.
|
||||
* @return `true` if installation was successful.
|
||||
*/
|
||||
bool
|
||||
install_steam_audio_drivers() {
|
||||
#ifdef STEAM_DRIVER_SUBDIR
|
||||
// MinGW's libnewdev.a is missing DiInstallDriverW() even though the headers have it,
|
||||
// so we have to load it at runtime. It's Vista or later, so it will always be available.
|
||||
auto newdev = LoadLibraryExW(L"newdev.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (!newdev) {
|
||||
BOOST_LOG(error) << "newdev.dll failed to load"sv;
|
||||
return false;
|
||||
}
|
||||
auto fg = util::fail_guard([newdev]() {
|
||||
FreeLibrary(newdev);
|
||||
});
|
||||
|
||||
auto fn_DiInstallDriverW = (decltype(DiInstallDriverW) *) GetProcAddress(newdev, "DiInstallDriverW");
|
||||
if (!fn_DiInstallDriverW) {
|
||||
BOOST_LOG(error) << "DiInstallDriverW() is missing"sv;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the current default audio device (if present)
|
||||
auto old_default_dev = default_device(device_enum);
|
||||
|
||||
// Install the Steam Streaming Speakers driver
|
||||
WCHAR driver_path[MAX_PATH] = {};
|
||||
ExpandEnvironmentStringsW(STEAM_AUDIO_DRIVER_PATH, driver_path, ARRAYSIZE(driver_path));
|
||||
if (fn_DiInstallDriverW(nullptr, driver_path, 0, nullptr)) {
|
||||
BOOST_LOG(info) << "Successfully installed Steam Streaming Speakers"sv;
|
||||
|
||||
// Wait for 5 seconds to allow the audio subsystem to reconfigure things before
|
||||
// modifying the default audio device or enumerating devices again.
|
||||
Sleep(5000);
|
||||
|
||||
// If there was a previous default device, restore that original device as the
|
||||
// default output device just in case installing the new one changed it.
|
||||
if (old_default_dev) {
|
||||
audio::wstring_t old_default_id;
|
||||
old_default_dev->GetId(&old_default_id);
|
||||
|
||||
for (int x = 0; x < (int) ERole_enum_count; ++x) {
|
||||
policy->SetDefaultEndpoint(old_default_id.get(), (ERole) x);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
auto err = GetLastError();
|
||||
switch (err) {
|
||||
case ERROR_ACCESS_DENIED:
|
||||
BOOST_LOG(warning) << "Administrator privileges are required to install Steam Streaming Speakers"sv;
|
||||
break;
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
BOOST_LOG(info) << "Steam audio drivers not found. This is expected if you don't have Steam installed."sv;
|
||||
break;
|
||||
default:
|
||||
BOOST_LOG(warning) << "Failed to install Steam audio drivers: "sv << err;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
BOOST_LOG(warning) << "Unable to install Steam Streaming Speakers on unknown architecture"sv;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
init() {
|
||||
auto status = CoCreateInstance(
|
||||
@ -893,12 +950,32 @@ namespace platf::audio {
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = CoCreateInstance(
|
||||
CLSID_MMDeviceEnumerator,
|
||||
nullptr,
|
||||
CLSCTX_ALL,
|
||||
IID_IMMDeviceEnumerator,
|
||||
(void **) &device_enum);
|
||||
|
||||
if (FAILED(status)) {
|
||||
BOOST_LOG(error) << "Couldn't create Device Enumerator: [0x"sv << util::hex(status).to_string_view() << ']';
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Install Steam Streaming Speakers if needed. We do this during init() to ensure
|
||||
// the sink information returned includes the new Steam Streaming Speakers device.
|
||||
if (config::audio.install_steam_drivers && !find_device_id_by_name("Steam Streaming Speakers"s)) {
|
||||
// This is best effort. Don't fail if it doesn't work.
|
||||
install_steam_audio_drivers();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
~audio_control_t() override {}
|
||||
|
||||
policy_t policy;
|
||||
audio::device_enum_t device_enum;
|
||||
std::string assigned_sink;
|
||||
};
|
||||
} // namespace platf::audio
|
||||
|
||||
@ -515,6 +515,18 @@
|
||||
stream audio, while muting the host PC speakers.
|
||||
</div>
|
||||
</div>
|
||||
<!--Install Steam Audio Drivers-->
|
||||
<div class="mb-3" v-if="platform === 'windows'">
|
||||
<label for="install_steam_audio_drivers" class="form-label">Install Steam Audio Drivers</label>
|
||||
<select id="install_steam_audio_drivers" class="form-select" v-model="config.install_steam_audio_drivers">
|
||||
<option value="disabled">Disabled</option>
|
||||
<option value="enabled">Enabled</option>
|
||||
</select>
|
||||
<div class="form-text">
|
||||
If Steam is installed, this will automatically install the Steam Streaming Speakers driver to support
|
||||
5.1/7.1 surround sound and muting host audio.
|
||||
</div>
|
||||
</div>
|
||||
<!--Adapter Name -->
|
||||
<div class="mb-3" v-if="platform === 'windows'">
|
||||
<label for="adapter_name" class="form-label">Adapter Name</label>
|
||||
@ -992,6 +1004,7 @@
|
||||
"amd_vbaq": "enabled",
|
||||
"capture": "",
|
||||
"controller": "enabled",
|
||||
"install_steam_audio_drivers": "enabled",
|
||||
"dwmflush": "enabled",
|
||||
"encoder": "",
|
||||
"fps": "[10,30,60,90,120]",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user