Merge pull request #15874 from marcelofg55/wasapi_device_change_21
Improved WASAPI driver so that it always uses the default audio device
This commit is contained in:
commit
e21eb2c0d3
@ -39,6 +39,69 @@ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
|
|||||||
const IID IID_IAudioClient = __uuidof(IAudioClient);
|
const IID IID_IAudioClient = __uuidof(IAudioClient);
|
||||||
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
|
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
|
||||||
|
|
||||||
|
static bool default_device_changed = false;
|
||||||
|
|
||||||
|
class CMMNotificationClient : public IMMNotificationClient {
|
||||||
|
LONG _cRef;
|
||||||
|
IMMDeviceEnumerator *_pEnumerator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CMMNotificationClient() : _cRef(1), _pEnumerator(NULL) { }
|
||||||
|
~CMMNotificationClient() { if ((_pEnumerator) != NULL) { (_pEnumerator)->Release(); (_pEnumerator) = NULL; } }
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef() {
|
||||||
|
return InterlockedIncrement(&_cRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE Release() {
|
||||||
|
ULONG ulRef = InterlockedDecrement(&_cRef);
|
||||||
|
if (0 == ulRef) {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
return ulRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) {
|
||||||
|
if (IID_IUnknown == riid) {
|
||||||
|
AddRef();
|
||||||
|
*ppvInterface = (IUnknown*)this;
|
||||||
|
} else if (__uuidof(IMMNotificationClient) == riid) {
|
||||||
|
AddRef();
|
||||||
|
*ppvInterface = (IMMNotificationClient*)this;
|
||||||
|
} else {
|
||||||
|
*ppvInterface = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) {
|
||||||
|
return S_OK;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) {
|
||||||
|
if (flow == eRender && role == eConsole) {
|
||||||
|
default_device_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static CMMNotificationClient notif_client;
|
||||||
|
|
||||||
Error AudioDriverWASAPI::init_device(bool reinit) {
|
Error AudioDriverWASAPI::init_device(bool reinit) {
|
||||||
|
|
||||||
WAVEFORMATEX *pwfex;
|
WAVEFORMATEX *pwfex;
|
||||||
@ -53,7 +116,7 @@ Error AudioDriverWASAPI::init_device(bool reinit) {
|
|||||||
hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device);
|
hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device);
|
||||||
if (reinit) {
|
if (reinit) {
|
||||||
// In case we're trying to re-initialize the device prevent throwing this error on the console,
|
// In case we're trying to re-initialize the device prevent throwing this error on the console,
|
||||||
// otherwise if there is currently no devie available this will spam the console.
|
// otherwise if there is currently no device available this will spam the console.
|
||||||
if (hr != S_OK) {
|
if (hr != S_OK) {
|
||||||
return ERR_CANT_OPEN;
|
return ERR_CANT_OPEN;
|
||||||
}
|
}
|
||||||
@ -61,6 +124,11 @@ Error AudioDriverWASAPI::init_device(bool reinit) {
|
|||||||
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
|
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = enumerator->RegisterEndpointNotificationCallback(¬if_client);
|
||||||
|
if (hr != S_OK) {
|
||||||
|
ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error");
|
||||||
|
}
|
||||||
|
|
||||||
hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&audio_client);
|
hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void **)&audio_client);
|
||||||
if (reinit) {
|
if (reinit) {
|
||||||
if (hr != S_OK) {
|
if (hr != S_OK) {
|
||||||
@ -87,7 +155,7 @@ Error AudioDriverWASAPI::init_device(bool reinit) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ERR_PRINTS("WASAPI: Unsupported number of channels (" + itos(wasapi_channels) + ")");
|
WARN_PRINTS("WASAPI: Unsupported number of channels (" + itos(wasapi_channels) + ")");
|
||||||
channels = 2;
|
channels = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +212,8 @@ Error AudioDriverWASAPI::finish_device() {
|
|||||||
if (audio_client) {
|
if (audio_client) {
|
||||||
if (active) {
|
if (active) {
|
||||||
audio_client->Stop();
|
audio_client->Stop();
|
||||||
|
audio_client->Release();
|
||||||
|
audio_client = NULL;
|
||||||
active = false;
|
active = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,6 +389,15 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (default_device_changed) {
|
||||||
|
Error err = ad->finish_device();
|
||||||
|
if (err != OK) {
|
||||||
|
ERR_PRINT("WASAPI: finish_device error");
|
||||||
|
}
|
||||||
|
|
||||||
|
default_device_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ad->audio_client) {
|
if (!ad->audio_client) {
|
||||||
Error err = ad->init_device(true);
|
Error err = ad->init_device(true);
|
||||||
if (err == OK) {
|
if (err == OK) {
|
||||||
|
Loading…
Reference in New Issue
Block a user