diff options
author | Deal <[email protected]> | 2023-09-23 00:33:09 +0800 |
---|---|---|
committer | GitHub <[email protected]> | 2023-09-22 16:33:09 +0000 |
commit | 6f33ba65d6470a99dac860dcd8472d47370be77f (patch) | |
tree | dc6fc9885625536b681c2267116adb207d109db6 | |
parent | 1b8c63910fc36a292ae591f5bedc8654c0173be9 (diff) |
UWP: migrate C++/CX to C++/WinRT (#916)
-rw-r--r-- | CMakeLists.txt | 28 | ||||
-rw-r--r-- | alc/alconfig.cpp | 10 | ||||
-rw-r--r-- | alc/backends/wasapi.cpp | 123 |
3 files changed, 78 insertions, 83 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b75514b2..7a01eb9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1062,19 +1062,8 @@ if(WIN32) set(HAVE_WASAPI 1) set(BACKENDS "${BACKENDS} WASAPI,") set(ALC_OBJS ${ALC_OBJS} alc/backends/wasapi.cpp alc/backends/wasapi.h) - if(ALSOFT_UWP) - set_source_files_properties(alc/backends/wasapi.cpp alc/alconfig.cpp PROPERTIES COMPILE_FLAGS /ZW) - endif() endif() endif() - - # Setup properly link flags for UWP - if(ALSOFT_UWP AND HAVE_WASAPI) - # Add compile and link flags required C++/CX - set(C_FLAGS "/Zc:twoPhase-" ${C_FLAGS}) - set(LINKER_FLAGS_DEBUG "/nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib ${LINKER_FLAGS_DEBUG}") - set(LINKER_FLAGS_RELEASE "/nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib ${LINKER_FLAGS_RELEASE}") - endif() endif() if(ALSOFT_REQUIRE_WINMM AND NOT HAVE_WINMM) message(FATAL_ERROR "Failed to enabled required WinMM backend") @@ -1419,13 +1408,20 @@ else() endif() target_link_libraries(${IMPL_TARGET} PRIVATE alcommon ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) - if(ALSOFT_UWP AND HAVE_WASAPI) + if(ALSOFT_UWP) + find_program(NUGET_EXE NAMES nuget) + if(NOT NUGET_EXE) + message("NUGET.EXE not found.") + message(FATAL_ERROR "Please install this executable, and run CMake again.") + endif() + + exec_program(${NUGET_EXE} + ARGS install "Microsoft.Windows.CppWinRT" -Version 2.0.230706.1 -ExcludeVersion -OutputDirectory "\"${CMAKE_BINARY_DIR}/packages\"") + set_target_properties(${IMPL_TARGET} PROPERTIES - LINK_FLAGS_DEBUG "${LINKER_FLAGS_DEBUG}" - LINK_FLAGS_RELEASE "${LINKER_FLAGS_RELEASE}" - LINK_FLAGS_MINSIZEREL "${LINKER_FLAGS_RELEASE}" - LINK_FLAGS_RELWITHDEBINFO "${LINKER_FLAGS_RELEASE}" + VS_PROJECT_IMPORT ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT/build/native/Microsoft.Windows.CppWinRT.props ) + target_link_libraries(${IMPL_TARGET} PRIVATE ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT/build/native/Microsoft.Windows.CppWinRT.targets) endif() if(NOT WIN32 AND NOT APPLE) diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index 03139abe..097ba3a0 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -45,6 +45,13 @@ #include "strutils.h" #include "vector.h" +#if defined(ALSOFT_UWP) +#include <winrt/Windows.Media.Core.h> // !!This is important!! +#include <winrt/Windows.Storage.h> +#include <winrt/Windows.Foundation.h> +#include <winrt/Windows.Foundation.Collections.h> +using namespace winrt; +#endif namespace { @@ -336,7 +343,8 @@ void ReadALConfig() if (!SHGetSpecialFolderPathW(nullptr, buffer, CSIDL_APPDATA, FALSE)) return; #else - auto buffer = Windows::Storage::ApplicationData::Current->RoamingFolder->Path->Data(); + winrt::Windows::Storage::ApplicationDataContainer localSettings = winrt::Windows::Storage::ApplicationData::Current().LocalSettings(); + auto buffer = Windows::Storage::ApplicationData::Current().RoamingFolder().Path(); #endif std::string filepath{wstr_to_utf8(buffer)}; filepath += "\\alsoft.ini"; diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index d06d7401..fc626fc6 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -73,8 +73,15 @@ #include "strutils.h" #if defined(ALSOFT_UWP) -#include <collection.h> -using namespace Platform; + +#include <winrt/Windows.Media.Core.h> // !!This is important!! +#include <winrt/Windows.Foundation.Collections.h> +#include <winrt/Windows.Devices.h> +#include <winrt/Windows.Foundation.h> +#include <winrt/Windows.Devices.Enumeration.h> +#include <winrt/Windows.Media.Devices.h> + +using namespace winrt; using namespace Windows::Foundation; using namespace Windows::Media::Devices; using namespace Windows::Devices::Enumeration; @@ -276,8 +283,8 @@ enum EDataFlow { #endif #if defined(ALSOFT_UWP) -using DeviceHandle = DeviceInformation^; -using EventRegistrationToken = Windows::Foundation::EventRegistrationToken; +using DeviceHandle = Windows::Devices::Enumeration::DeviceInformation; +using EventRegistrationToken = winrt::event_token; #else using DeviceHandle = ComPtr<IMMDevice>; #endif @@ -329,11 +336,11 @@ static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) guid = UnknownGuid; } #else - std::string name{wstr_to_utf8(device->Name->Data())}; + std::string name{wstr_to_utf8(device.Name())}; std::string guid; // device->Id is DeviceInterfacePath: \\?\SWD#MMDEVAPI#{0.0.0.00000000}.{a21c17a0-fc1d-405e-ab5a-b513422b57d1}#{e6327cad-dcec-4949-ae8a-991e976a79d2} - Platform::String^ devIfPath = device->Id; - if(auto devIdStart = wcsstr(devIfPath->Data(), L"}.")) + auto devIfPath = device.Id(); + if(auto devIdStart = wcsstr(devIfPath.data(), L"}.")) { devIdStart += 2; // L"}." if(auto devIdStartEnd = wcschr(devIdStart, L'#')) @@ -388,35 +395,32 @@ struct DeviceHelper final : private IMMNotificationClient */ mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); - mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged += - ref new TypedEventHandler<Platform::Object ^, DefaultAudioRenderDeviceChangedEventArgs ^>( - [this](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { - if(args->Role == AudioDeviceRole::Default) - { - const std::string msg{"Default playback device changed: "+ - wstr_to_utf8(args->Id->Data())}; - alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, - msg); - } + mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged([this](const IInspectable& /*sender*/, const DefaultAudioRenderDeviceChangedEventArgs& args) { + if (args.Role() == AudioDeviceRole::Default) + { + const std::string msg{ "Default playback device changed: " + + wstr_to_utf8(args.Id())}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, + msg); + } }); - mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged += - ref new TypedEventHandler<Platform::Object ^, DefaultAudioCaptureDeviceChangedEventArgs ^>( - [this](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { - if(args->Role == AudioDeviceRole::Default) - { - const std::string msg{"Default capture device changed: "+ - wstr_to_utf8(args->Id->Data())}; - alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, - msg); - } + + mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged([this](const IInspectable& /*sender*/, const DefaultAudioCaptureDeviceChangedEventArgs& args) { + if (args.Role() == AudioDeviceRole::Default) + { + const std::string msg{ "Default capture device changed: " + + wstr_to_utf8(args.Id()) }; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, + msg); + } }); #endif } ~DeviceHelper() { #if defined(ALSOFT_UWP) - MediaDevice::DefaultAudioRenderDeviceChanged -= mRenderDeviceChangedToken; - MediaDevice::DefaultAudioCaptureDeviceChanged -= mCaptureDeviceChangedToken; + MediaDevice::DefaultAudioRenderDeviceChanged(mRenderDeviceChangedToken); + MediaDevice::DefaultAudioCaptureDeviceChanged(mCaptureDeviceChangedToken); if(mActiveClientEvent != nullptr) CloseHandle(mActiveClientEvent); @@ -612,21 +616,16 @@ struct DeviceHelper final : private IMMNotificationClient return hr; #else const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; - Platform::String^ devIfPath = + auto devIfPath = devid.empty() ? (flow == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole)) - : ref new Platform::String(devid.data()); - if (!devIfPath) + : winrt::hstring(devid.data()); + if (devIfPath.empty()) return E_POINTER; - Concurrency::task<DeviceInformation^> createDeviceOp( - DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface)); - auto status = createDeviceOp.then([&](DeviceInformation^ deviceInfo) - { - device = deviceInfo; - }).wait(); - if(status != Concurrency::task_status::completed) - { + + auto&& deviceInfo = DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface).get(); + if (!deviceInfo) return E_NOINTERFACE; - } + device = deviceInfo; return S_OK; #endif } @@ -638,7 +637,7 @@ struct DeviceHelper final : private IMMNotificationClient HRESULT activateAudioClient(_In_ DeviceHandle &device, _In_ REFIID iid, void **ppv) { ComPtr<IActivateAudioInterfaceAsyncOperation> asyncOp; - HRESULT hr{ActivateAudioInterfaceAsync(device->Id->Data(), iid, nullptr, this, + HRESULT hr{ActivateAudioInterfaceAsync(device.Id().data(), iid, nullptr, this, al::out_ptr(asyncOp))}; if(FAILED(hr)) return hr; @@ -713,40 +712,32 @@ struct DeviceHelper final : private IMMNotificationClient const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; auto DefaultAudioId = flowdir == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole); - if (!DefaultAudioId) + if (DefaultAudioId.empty()) return defaultId; - Concurrency::task<DeviceInformation ^> createDefaultOp(DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface)); - auto task_status = createDefaultOp.then([&defaultId](DeviceInformation ^ deviceInfo) - { - if(deviceInfo) - defaultId = deviceInfo->Id->Data(); - }).wait(); - if(task_status != Concurrency::task_group_status::completed) + + auto deviceInfo = DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface).get(); + if(!deviceInfo) return defaultId; // Get the string identifier of the audio renderer auto AudioSelector = flowdir == eRender ? MediaDevice::GetAudioRenderSelector() : MediaDevice::GetAudioCaptureSelector(); // Setup the asynchronous callback - Concurrency::task<DeviceInformationCollection ^> enumOperation( - DeviceInformation::FindAllAsync(AudioSelector, /*PropertyList*/nullptr, DeviceInformationKind::DeviceInterface)); - task_status = enumOperation.then([this,&list](DeviceInformationCollection ^ DeviceInfoCollection) + auto&& DeviceInfoCollection = DeviceInformation::FindAllAsync(AudioSelector, /*PropertyList*/nullptr, DeviceInformationKind::DeviceInterface).get(); + if(DeviceInfoCollection) { - if(DeviceInfoCollection) - { - try { - auto deviceCount = DeviceInfoCollection->Size; - for(unsigned int i{0};i < deviceCount;++i) - { - DeviceInformation^ deviceInfo = DeviceInfoCollection->GetAt(i); - if(deviceInfo) - std::ignore = AddDevice(deviceInfo, deviceInfo->Id->Data(), list); - } - } - catch (Platform::Exception ^ e) { + try { + auto deviceCount = DeviceInfoCollection.Size(); + for(unsigned int i{0};i < deviceCount;++i) + { + deviceInfo = DeviceInfoCollection.GetAt(i); + if(deviceInfo) + std::ignore = AddDevice(deviceInfo, deviceInfo.Id().data(), list); } } - }).wait(); + catch (std::exception& /*ex*/) { + } + } #endif return defaultId; |