mirror of
https://github.com/LizardByte/Sunshine.git
synced 2026-02-04 16:55:37 +00:00
fix(audio-info): crash when device name contains special characters (#4095)
This commit is contained in:
@ -6,17 +6,13 @@
|
||||
|
||||
// platform includes
|
||||
#include <Audioclient.h>
|
||||
#include <codecvt>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
#include <mmdeviceapi.h>
|
||||
#include <roapi.h>
|
||||
#include <synchapi.h>
|
||||
|
||||
// lib includes
|
||||
#include <boost/locale.hpp>
|
||||
|
||||
// local includes
|
||||
#include "src/platform/windows/utf_utils.h"
|
||||
#include "src/utility.h"
|
||||
|
||||
DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING
|
||||
@ -35,7 +31,7 @@ namespace audio {
|
||||
|
||||
template<class T>
|
||||
void co_task_free(T *p) {
|
||||
CoTaskMemFree((LPVOID) p);
|
||||
CoTaskMemFree(static_cast<LPVOID>(p));
|
||||
}
|
||||
|
||||
using device_enum_t = util::safe_ptr<IMMDeviceEnumerator, Release<IMMDeviceEnumerator>>;
|
||||
@ -63,10 +59,6 @@ namespace audio {
|
||||
PROPVARIANT prop;
|
||||
};
|
||||
|
||||
const wchar_t *no_null(const wchar_t *str) {
|
||||
return str ? str : L"Unknown";
|
||||
}
|
||||
|
||||
struct format_t {
|
||||
std::string_view name;
|
||||
int channels;
|
||||
@ -118,7 +110,11 @@ namespace audio {
|
||||
wave_format->nAvgBytesPerSec = wave_format->nSamplesPerSec * wave_format->nBlockAlign;
|
||||
|
||||
if (wave_format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
||||
((PWAVEFORMATEXTENSIBLE) wave_format.get())->dwChannelMask = format.channel_mask;
|
||||
// Access the extended format through proper offsetting
|
||||
// WAVEFORMATEXTENSIBLE has WAVEFORMATEX as first member, so this is safe
|
||||
const auto ext_format =
|
||||
static_cast<PWAVEFORMATEXTENSIBLE>(static_cast<void *>(wave_format.get()));
|
||||
ext_format->dwChannelMask = format.channel_mask;
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +124,7 @@ namespace audio {
|
||||
IID_IAudioClient,
|
||||
CLSCTX_ALL,
|
||||
nullptr,
|
||||
(void **) &audio_client
|
||||
static_cast<void **>(static_cast<void *>(&audio_client))
|
||||
);
|
||||
|
||||
if (FAILED(status)) {
|
||||
@ -186,7 +182,7 @@ namespace audio {
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring device_state_string = L"Unknown"s;
|
||||
std::wstring device_state_string;
|
||||
switch (device_state) {
|
||||
case DEVICE_STATE_ACTIVE:
|
||||
device_state_string = L"Active"s;
|
||||
@ -200,28 +196,36 @@ namespace audio {
|
||||
case DEVICE_STATE_NOTPRESENT:
|
||||
device_state_string = L"Not present"s;
|
||||
break;
|
||||
default:
|
||||
device_state_string = L"Unknown"s;
|
||||
break;
|
||||
}
|
||||
|
||||
std::wstring current_format = L"Unknown"s;
|
||||
std::string current_format = "Unknown";
|
||||
for (const auto &format : formats) {
|
||||
// This will fail for any format that's not the mix format for this device,
|
||||
// so we can take the first match as the current format to display.
|
||||
auto audio_client = make_audio_client(device, format);
|
||||
if (audio_client) {
|
||||
current_format = boost::locale::conv::utf_to_utf<wchar_t>(format.name.data());
|
||||
if (auto audio_client = make_audio_client(device, format)) {
|
||||
current_format = std::string(format.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::wcout
|
||||
<< L"===== Device ====="sv << std::endl
|
||||
<< L"Device ID : "sv << wstring.get() << std::endl
|
||||
<< L"Device name : "sv << no_null((LPWSTR) device_friendly_name.prop.pszVal) << std::endl
|
||||
<< L"Adapter name : "sv << no_null((LPWSTR) adapter_friendly_name.prop.pszVal) << std::endl
|
||||
<< L"Device description : "sv << no_null((LPWSTR) device_desc.prop.pszVal) << std::endl
|
||||
<< L"Device state : "sv << device_state_string << std::endl
|
||||
<< L"Current format : "sv << current_format << std::endl
|
||||
<< std::endl;
|
||||
auto safe_wstring_output = [](const wchar_t *wstr) -> std::string {
|
||||
if (!wstr) {
|
||||
return "Unknown";
|
||||
}
|
||||
return utf_utils::to_utf8(std::wstring(wstr));
|
||||
};
|
||||
|
||||
std::cout << "===== Device =====" << std::endl;
|
||||
std::cout << "Device ID : " << utf_utils::to_utf8(std::wstring(wstring.get())) << std::endl;
|
||||
std::cout << "Device name : " << safe_wstring_output(device_friendly_name.prop.pwszVal) << std::endl;
|
||||
std::cout << "Adapter name : " << safe_wstring_output(adapter_friendly_name.prop.pwszVal) << std::endl;
|
||||
std::cout << "Device description : " << safe_wstring_output(device_desc.prop.pwszVal) << std::endl;
|
||||
std::cout << "Device state : " << utf_utils::to_utf8(device_state_string) << std::endl;
|
||||
std::cout << "Current format : " << current_format << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
} // namespace audio
|
||||
|
||||
@ -268,15 +272,13 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT status;
|
||||
|
||||
audio::device_enum_t device_enum;
|
||||
status = CoCreateInstance(
|
||||
HRESULT status = CoCreateInstance(
|
||||
CLSID_MMDeviceEnumerator,
|
||||
nullptr,
|
||||
CLSCTX_ALL,
|
||||
IID_IMMDeviceEnumerator,
|
||||
(void **) &device_enum
|
||||
static_cast<void **>(static_cast<void *>(&device_enum))
|
||||
);
|
||||
|
||||
if (FAILED(status)) {
|
||||
|
||||
Reference in New Issue
Block a user