22 #include "../../SDL_internal.h" 29 #if SDL_AUDIO_DRIVER_WASAPI && defined(__WINRT__) 32 #include <windows.ui.core.h> 33 #include <windows.devices.enumeration.h> 34 #include <windows.media.devices.h> 35 #include <wrl/implements.h> 38 #include "../../core/windows/SDL_windows.h" 41 #include "../SDL_audio_c.h" 42 #include "../SDL_sysaudio.h" 48 #include <mmdeviceapi.h> 49 #include <audioclient.h> 53 using namespace Windows::Devices::Enumeration;
54 using namespace Windows::Media::Devices;
56 using namespace Microsoft::WRL;
58 class SDL_WasapiDeviceEventHandler
61 SDL_WasapiDeviceEventHandler(
const SDL_bool _iscapture);
62 ~SDL_WasapiDeviceEventHandler();
63 void OnDeviceAdded(DeviceWatcher^ sender, DeviceInformation^ args);
64 void OnDeviceRemoved(DeviceWatcher^ sender, DeviceInformationUpdate^ args);
65 void OnDeviceUpdated(DeviceWatcher^ sender, DeviceInformationUpdate^ args);
66 void OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args);
67 void OnDefaultCaptureDeviceChanged(Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args);
71 DeviceWatcher^ watcher;
72 Windows::Foundation::EventRegistrationToken added_handler;
73 Windows::Foundation::EventRegistrationToken removed_handler;
74 Windows::Foundation::EventRegistrationToken updated_handler;
75 Windows::Foundation::EventRegistrationToken default_changed_handler;
78 SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(
const SDL_bool _iscapture)
79 : iscapture(_iscapture)
80 , watcher(DeviceInformation::CreateWatcher(_iscapture ? DeviceClass::AudioCapture : DeviceClass::AudioRender))
86 added_handler = watcher->Added +=
ref new TypedEventHandler<DeviceWatcher^, DeviceInformation^>([
this](DeviceWatcher^ sender, DeviceInformation^ args) { OnDeviceAdded(sender, args); } );
87 removed_handler = watcher->Removed +=
ref new TypedEventHandler<DeviceWatcher^, DeviceInformationUpdate^>([
this](DeviceWatcher^ sender, DeviceInformationUpdate^ args) { OnDeviceRemoved(sender, args); } );
88 updated_handler = watcher->Updated +=
ref new TypedEventHandler<DeviceWatcher^, DeviceInformationUpdate^>([
this](DeviceWatcher^ sender, DeviceInformationUpdate^ args) { OnDeviceUpdated(sender, args); } );
90 default_changed_handler = MediaDevice::DefaultAudioCaptureDeviceChanged +=
ref new TypedEventHandler<Platform::Object^, DefaultAudioCaptureDeviceChangedEventArgs^>([
this](Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args) { OnDefaultCaptureDeviceChanged(sender, args); } );
92 default_changed_handler = MediaDevice::DefaultAudioRenderDeviceChanged +=
ref new TypedEventHandler<Platform::Object^, DefaultAudioRenderDeviceChangedEventArgs^>([
this](Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args) { OnDefaultRenderDeviceChanged(sender, args); } );
97 SDL_WasapiDeviceEventHandler::~SDL_WasapiDeviceEventHandler()
100 watcher->Added -= added_handler;
101 watcher->Removed -= removed_handler;
102 watcher->Updated -= updated_handler;
108 MediaDevice::DefaultAudioCaptureDeviceChanged -= default_changed_handler;
110 MediaDevice::DefaultAudioRenderDeviceChanged -= default_changed_handler;
115 SDL_WasapiDeviceEventHandler::OnDeviceAdded(DeviceWatcher^ sender, DeviceInformation^ info)
126 SDL_WasapiDeviceEventHandler::OnDeviceRemoved(DeviceWatcher^ sender, DeviceInformationUpdate^ info)
133 SDL_WasapiDeviceEventHandler::OnDeviceUpdated(DeviceWatcher^ sender, DeviceInformationUpdate^ args)
139 SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args)
146 SDL_WasapiDeviceEventHandler::OnDefaultCaptureDeviceChanged(Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args)
153 static SDL_WasapiDeviceEventHandler *playback_device_event_handler;
154 static SDL_WasapiDeviceEventHandler *capture_device_event_handler;
163 delete playback_device_event_handler;
164 playback_device_event_handler =
nullptr;
165 delete capture_device_event_handler;
166 capture_device_event_handler =
nullptr;
174 playback_device_event_handler =
new SDL_WasapiDeviceEventHandler(
SDL_FALSE);
175 capture_device_event_handler =
new SDL_WasapiDeviceEventHandler(
SDL_TRUE);
178 struct SDL_WasapiActivationHandler :
public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >
180 SDL_WasapiActivationHandler() :
device(nullptr) {}
181 STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation *operation);
186 SDL_WasapiActivationHandler::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *async)
189 IUnknown *iunknown =
nullptr;
190 const HRESULT ret = async->GetActivateResult(&result, &iunknown);
193 iunknown->QueryInterface(IID_PPV_ARGS(&
device->hidden->client));
194 if (
device->hidden->client) {
208 ((SDL_WasapiActivationHandler *) handler)->Release();
215 Platform::String^ defdevid;
217 if (devid ==
nullptr) {
218 defdevid =
_this->iscapture ? MediaDevice::GetDefaultAudioCaptureId(AudioDeviceRole::Default) : MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
220 devid = defdevid->Data();
226 ComPtr<SDL_WasapiActivationHandler> handler = Make<SDL_WasapiActivationHandler>();
227 if (handler ==
nullptr) {
228 return SDL_SetError(
"Failed to allocate WASAPI activation handler");
231 handler.Get()->AddRef();
232 handler.Get()->device =
_this;
233 _this->hidden->activation_handler = handler.Get();
236 IActivateAudioInterfaceAsyncOperation *async =
nullptr;
237 const HRESULT ret = ActivateAudioInterfaceAsync(devid, __uuidof(IAudioClient),
nullptr, handler.Get(), &async);
239 if (async !=
nullptr) {
244 handler.Get()->Release();
274 #endif // SDL_AUDIO_DRIVER_WASAPI && defined(__WINRT__)
void WASAPI_AddDevice(const SDL_bool iscapture, const char *devname, LPCWSTR devid)
void WASAPI_UnrefDevice(_THIS)
void WASAPI_BeginLoopIteration(_THIS)
int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
int WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
void WASAPI_PlatformThreadDeinit(_THIS)
void WASAPI_PlatformDeinit(void)
int WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
static SDL_VideoDevice * _this
static SDL_AudioDeviceID device
void WASAPI_RefDevice(_THIS)
void WASAPI_EnumerateEndpoints(void)
#define WIN_StringToUTF8(S)
void WASAPI_RemoveDevice(const SDL_bool iscapture, LPCWSTR devid)
int WASAPI_PlatformInit(void)
SDL_atomic_t WASAPI_DefaultPlaybackGeneration
#define SDL_assert(condition)
SDL_atomic_t WASAPI_DefaultCaptureGeneration
void WASAPI_PlatformDeleteActivationHandler(void *handler)
void WASAPI_PlatformThreadInit(_THIS)