summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Mitchell <kevmitch@gmail.com>2014-11-14 22:47:28 -0800
committerKevin Mitchell <kevmitch@gmail.com>2014-11-17 04:13:52 -0800
commit3da6f723c6ceba468412f2282ab4f7958ca6f5d7 (patch)
treea175f6a7eff45230f1cb5f473278296aa15e8710
parente28102f1a8d4c5284fa2d2eb13fe4147eefcd02b (diff)
downloadmpv-3da6f723c6ceba468412f2282ab4f7958ca6f5d7.tar.bz2
mpv-3da6f723c6ceba468412f2282ab4f7958ca6f5d7.tar.xz
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.
-rw-r--r--audio/out/ao_wasapi.c23
-rwxr-xr-xaudio/out/ao_wasapi_utils.c15
-rwxr-xr-xaudio/out/ao_wasapi_utils.h2
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);