From 3da6f723c6ceba468412f2282ab4f7958ca6f5d7 Mon Sep 17 00:00:00 2001 From: Kevin Mitchell Date: Fri, 14 Nov 2014 22:47:28 -0800 Subject: ao/wasapi: tidy up better on failure Before, failures, particularly in the thread loop init, could lead to a bad state for the duration of mpvs execution. Make sure that everything that was initialized gets properly and safely uninitialized. --- audio/out/ao_wasapi.c | 23 +++++++++++------------ audio/out/ao_wasapi_utils.c | 15 +++++++++++++-- audio/out/ao_wasapi_utils.h | 2 ++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index c2c28d2e39..42317f7b0e 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -116,6 +116,7 @@ static DWORD __stdcall ThreadLoop(void *lpParameter) return -1; struct wasapi_state *state = (struct wasapi_state *)ao->priv; int thread_ret; + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); state->init_ret = wasapi_thread_init(ao); SetEvent(state->init_done); @@ -124,7 +125,7 @@ static DWORD __stdcall ThreadLoop(void *lpParameter) goto exit_label; } - MSG msg; + DWORD waitstatus; HANDLE playcontrol[] = {state->hUninit, state->hFeed, state->hForceFeed, NULL}; @@ -134,7 +135,6 @@ static DWORD __stdcall ThreadLoop(void *lpParameter) QS_POSTMESSAGE | QS_SENDMESSAGE); switch (waitstatus) { case WAIT_OBJECT_0: /*shutdown*/ - wasapi_thread_uninit(ao); thread_ret = 0; goto exit_label; case (WAIT_OBJECT_0 + 1): /* feed */ @@ -145,9 +145,7 @@ static DWORD __stdcall ThreadLoop(void *lpParameter) SetEvent(state->hFeedDone); break; case (WAIT_OBJECT_0 + 3): /* messages to dispatch (COM marshalling) */ - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - DispatchMessage(&msg); - } + wasapi_dispatch(); break; default: MP_ERR(ao, "Unhandled case in thread loop"); @@ -156,11 +154,9 @@ static DWORD __stdcall ThreadLoop(void *lpParameter) } } exit_label: - /* dispatch any possible pending messages */ - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - DispatchMessage(&msg); - } + wasapi_thread_uninit(ao); + CoUninitialize(); return thread_ret; } @@ -224,6 +220,7 @@ static int init(struct ao *ao) /* failed to init events */ return -1; } + state->init_ret = E_FAIL; state->threadLoop = (HANDLE)CreateThread(NULL, 0, &ThreadLoop, ao, 0, NULL); if (!state->threadLoop) { @@ -231,16 +228,18 @@ static int init(struct ao *ao) MP_ERR(ao, "Failed to create thread\n"); return -1; } + WaitForSingleObject(state->init_done, INFINITE); /* wait on init complete */ if (state->init_ret != S_OK) { - if (!ao->probing) { + if (!ao->probing) MP_ERR(ao, "Received failure from audio thread\n"); - } + if (state->VistaBlob.hAvrt) + FreeLibrary(state->VistaBlob.hAvrt); return -1; } - MP_DBG(ao, "Init wasapi done\n"); wasapi_setup_proxies(state); + MP_DBG(ao, "Init wasapi done\n"); return 0; } diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index e54cbcd0bc..69bbefe5ef 100755 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -921,13 +921,20 @@ exit_label: return hr; } +void wasapi_dispatch(void) +{ + /* dispatch any possible pending messages */ + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); +} + HRESULT wasapi_thread_init(struct ao *ao) { struct wasapi_state *state = (struct wasapi_state *)ao->priv; HRESULT hr; MP_DBG(ao, "Init wasapi thread\n"); state->initial_volume = -1.0; - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); char *device = state->opt_device; if (!device || !device[0]) @@ -1010,10 +1017,14 @@ void wasapi_thread_uninit(struct ao *ao) { struct wasapi_state *state = (struct wasapi_state *)ao->priv; + wasapi_dispatch(); + if (state->pAudioClient) IAudioClient_Stop(state->pAudioClient); - if (state->opt_exclusive) + if (state->opt_exclusive && + state->pEndpointVolume && + state->initial_volume > 0 ) IAudioEndpointVolume_SetMasterVolumeLevelScalar(state->pEndpointVolume, state->initial_volume, NULL); diff --git a/audio/out/ao_wasapi_utils.h b/audio/out/ao_wasapi_utils.h index d0ba4f0222..24d8daffbc 100755 --- a/audio/out/ao_wasapi_utils.h +++ b/audio/out/ao_wasapi_utils.h @@ -37,6 +37,8 @@ int wasapi_enumerate_devices(struct mp_log *log, struct ao *ao, int wasapi_validate_device(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param); + +void wasapi_dispatch(void); HRESULT wasapi_thread_init(struct ao *ao); void wasapi_thread_uninit(struct ao *ao); -- cgit v1.2.3