mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	Improved WASAPI driver so that it always uses the default audio device
This commit is contained in:
		
							parent
							
								
									eb9fa02fbd
								
							
						
					
					
						commit
						d5afcf7ab1
					
				
					 1 changed files with 87 additions and 1 deletions
				
			
		|  | @ -40,6 +40,76 @@ const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); | |||
| const IID IID_IAudioClient = __uuidof(IAudioClient); | ||||
| 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) { | ||||
| 
 | ||||
| 	WAVEFORMATEX *pwfex; | ||||
|  | @ -54,7 +124,7 @@ Error AudioDriverWASAPI::init_device(bool reinit) { | |||
| 	hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device); | ||||
| 	if (reinit) { | ||||
| 		// 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) { | ||||
| 			return ERR_CANT_OPEN; | ||||
| 		} | ||||
|  | @ -62,6 +132,11 @@ Error AudioDriverWASAPI::init_device(bool reinit) { | |||
| 		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); | ||||
| 	if (reinit) { | ||||
| 		if (hr != S_OK) { | ||||
|  | @ -148,6 +223,8 @@ Error AudioDriverWASAPI::finish_device() { | |||
| 	if (audio_client) { | ||||
| 		if (active) { | ||||
| 			audio_client->Stop(); | ||||
| 			audio_client->Release(); | ||||
| 			audio_client = NULL; | ||||
| 			active = false; | ||||
| 		} | ||||
| 	} | ||||
|  | @ -323,6 +400,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) { | ||||
| 			Error err = ad->init_device(true); | ||||
| 			if (err == OK) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Marcelo Fernandez
						Marcelo Fernandez