#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_WASAPI && !defined(__WINRT__)
#include "../../core/windows/SDL_windows.h"
#include "../../core/windows/SDL_immdevice.h"
#include "SDL_audio.h"
#include "SDL_timer.h"
#include "../SDL_audio_c.h"
#include "../SDL_sysaudio.h"
#include <audioclient.h>
#include "SDL_wasapi.h"
static HMODULE libavrt = NULL;
typedef HANDLE(WINAPI *pfnAvSetMmThreadCharacteristicsW)(LPCWSTR, LPDWORD);
typedef BOOL(WINAPI *pfnAvRevertMmThreadCharacteristics)(HANDLE);
static pfnAvSetMmThreadCharacteristicsW pAvSetMmThreadCharacteristicsW = NULL;
static pfnAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL;
static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32,{ 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
int
WASAPI_PlatformInit(void)
{
if (SDL_IMMDevice_Init() < 0) {
return -1;
}
libavrt = LoadLibrary(TEXT("avrt.dll"));
if (libavrt) {
pAvSetMmThreadCharacteristicsW = (pfnAvSetMmThreadCharacteristicsW) GetProcAddress(libavrt, "AvSetMmThreadCharacteristicsW");
pAvRevertMmThreadCharacteristics = (pfnAvRevertMmThreadCharacteristics) GetProcAddress(libavrt, "AvRevertMmThreadCharacteristics");
}
return 0;
}
void
WASAPI_PlatformDeinit(void)
{
if (libavrt) {
FreeLibrary(libavrt);
libavrt = NULL;
}
pAvSetMmThreadCharacteristicsW = NULL;
pAvRevertMmThreadCharacteristics = NULL;
SDL_IMMDevice_Quit();
}
void
WASAPI_PlatformThreadInit(_THIS)
{
if (SUCCEEDED(WIN_CoInitialize())) {
this->hidden->coinitialized = SDL_TRUE;
}
if (pAvSetMmThreadCharacteristicsW) {
DWORD idx = 0;
this->hidden->task = pAvSetMmThreadCharacteristicsW(L"Pro Audio", &idx);
}
}
void
WASAPI_PlatformThreadDeinit(_THIS)
{
if (this->hidden->task && pAvRevertMmThreadCharacteristics) {
pAvRevertMmThreadCharacteristics(this->hidden->task);
this->hidden->task = NULL;
}
if (this->hidden->coinitialized) {
WIN_CoUninitialize();
this->hidden->coinitialized = SDL_FALSE;
}
}
int
WASAPI_ActivateDevice(_THIS, const SDL_bool isrecovery)
{
IMMDevice *device = NULL;
HRESULT ret;
if (SDL_IMMDevice_Get(this->hidden->devid, &device, this->iscapture) < 0) {
this->hidden->client = NULL;
return -1;
}
ret = IMMDevice_Activate(device, &SDL_IID_IAudioClient, CLSCTX_ALL, NULL, (void **) &this->hidden->client);
IMMDevice_Release(device);
if (FAILED(ret)) {
SDL_assert(this->hidden->client == NULL);
return WIN_SetErrorFromHRESULT("WASAPI can't activate audio endpoint", ret);
}
SDL_assert(this->hidden->client != NULL);
if (WASAPI_PrepDevice(this, isrecovery) == -1) {
return -1;
}
return 0;
}
void
WASAPI_EnumerateEndpoints(void)
{
SDL_IMMDevice_EnumerateEndpoints(SDL_FALSE);
}
int
WASAPI_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
{
return SDL_IMMDevice_GetDefaultAudioInfo(name, spec, iscapture);
}
void
WASAPI_PlatformDeleteActivationHandler(void *handler)
{
SDL_assert(!"This function should have only been called on WinRT.");
}
#endif