diff options
Diffstat (limited to 'audio/out')
-rw-r--r-- | audio/out/ao_wasapi.c | 268 | ||||
-rwxr-xr-x | audio/out/ao_wasapi.h | 29 | ||||
-rwxr-xr-x | audio/out/ao_wasapi_utils.c | 152 | ||||
-rwxr-xr-x | audio/out/ao_wasapi_utils.h | 25 |
4 files changed, 203 insertions, 271 deletions
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index 79f8dcf665..a496ff9aa6 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -32,13 +32,7 @@ #include "audio/out/ao_wasapi.h" #include "audio/out/ao_wasapi_utils.h" -#include "options/m_option.h" -#include "options/m_config.h" #include "audio/format.h" -#include "common/msg.h" -#include "misc/ring.h" -#include "ao.h" -#include "internal.h" #include "compat/atomics.h" #include "osdep/timer.h" @@ -47,61 +41,6 @@ #define SAFE_RELEASE(unk, release) \ do { if ((unk) != NULL) { release; (unk) = NULL; } } while(0) -static int thread_init(struct ao *ao) -{ - struct wasapi_state *state = (struct wasapi_state *)ao->priv; - HRESULT hr; - CoInitialize(NULL); - - if (!state->opt_device) { - IMMDeviceEnumerator *pEnumerator; - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, - &IID_IMMDeviceEnumerator, (void**)&pEnumerator); - EXIT_ON_ERROR(hr); - - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(pEnumerator, - eRender, eConsole, - &state->pDevice); - SAFE_RELEASE(pEnumerator, IMMDeviceEnumerator_Release(pEnumerator)); - - char *id = wasapi_get_device_id(state->pDevice); - MP_VERBOSE(ao, "default device ID: %s\n", id); - free(id); - } else { - hr = wasapi_find_and_load_device(ao, &state->pDevice, state->opt_device); - } - EXIT_ON_ERROR(hr); - - char *name = wasapi_get_device_name(state->pDevice); - MP_VERBOSE(ao, "device loaded: %s\n", name); - free(name); - - hr = IMMDeviceActivator_Activate(state->pDevice, &IID_IAudioClient, - CLSCTX_ALL, NULL, (void **)&state->pAudioClient); - EXIT_ON_ERROR(hr); - - hr = IMMDeviceActivator_Activate(state->pDevice, &IID_IAudioEndpointVolume, - CLSCTX_ALL, NULL, - (void **)&state->pEndpointVolume); - EXIT_ON_ERROR(hr); - IAudioEndpointVolume_QueryHardwareSupport(state->pEndpointVolume, - &state->vol_hw_support); - - state->init_ret = wasapi_find_formats(ao); /* Probe support formats */ - if (state->init_ret) - goto exit_label; - if (!wasapi_fix_format(state)) { /* now that we're sure what format to use */ - MP_VERBOSE(ao, "thread_init OK!\n"); - SetEvent(state->init_done); - return state->init_ret; - } -exit_label: - state->init_ret = -1; - SetEvent(state->init_done); - return -1; -} - - static double get_device_delay(struct wasapi_state *state) { UINT64 sample_count = state->sample_count; UINT64 position, qpc_position; @@ -160,7 +99,8 @@ static void thread_feed(struct ao *ao) frame_count, 0); EXIT_ON_ERROR(hr); - state->sample_count += frame_count; + mp_atomic_add_and_fetch(&state->sample_count, frame_count); + mp_memory_barrier(); return; exit_label: @@ -168,131 +108,48 @@ exit_label: return; } -static void thread_pause(struct ao *ao) -{ - struct wasapi_state *state = (struct wasapi_state *)ao->priv; - - state->is_playing = 0; - IAudioClient_Stop(state->pAudioClient); - IAudioClient_Reset(state->pAudioClient); - state->sample_count = 0; - mp_memory_barrier(); -} - -static void thread_resume(struct ao *ao) -{ - struct wasapi_state *state = (struct wasapi_state *)ao->priv; - - state->is_playing = 1; - thread_feed(ao); - IAudioClient_Start(state->pAudioClient); -} - -static void thread_reset(struct ao *ao) -{ - thread_pause(ao); -} - -static void thread_getVol(wasapi_state *state) -{ - IAudioEndpointVolume_GetMasterVolumeLevelScalar(state->pEndpointVolume, - &state->audio_volume); - SetEvent(state->hDoneVol); -} - -static void thread_setVol(wasapi_state *state) -{ - IAudioEndpointVolume_SetMasterVolumeLevelScalar(state->pEndpointVolume, - state->audio_volume, NULL); - SetEvent(state->hDoneVol); -} - -static void thread_uninit(wasapi_state *state) -{ - if (state->pAudioClient) - IAudioClient_Stop(state->pAudioClient); - if (state->pRenderClient) - IAudioRenderClient_Release(state->pRenderClient); - if (state->pAudioClock) - IAudioClock_Release(state->pAudioClock); - if (state->pAudioClient) - IAudioClient_Release(state->pAudioClient); - if (state->pDevice) - IMMDevice_Release(state->pDevice); - if (state->hTask) - state->VistaBlob.pAvRevertMmThreadCharacteristics(state->hTask); - CoUninitialize(); - ExitThread(0); -} - -static void audio_drain(struct ao *ao) -{ - struct wasapi_state *state = (struct wasapi_state *)ao->priv; - while (1) { - if (WaitForSingleObject(state->hFeed,2000) == WAIT_OBJECT_0 && - ao->api->get_delay(ao)) - { - thread_feed(ao); - } else - break; - } -} - static DWORD __stdcall ThreadLoop(void *lpParameter) { struct ao *ao = lpParameter; - int feedwatch = 0; if (!ao || !ao->priv) return -1; struct wasapi_state *state = (struct wasapi_state *)ao->priv; - if (thread_init(ao)) + if (wasapi_thread_init(ao)) goto exit_label; + MSG msg; DWORD waitstatus = WAIT_FAILED; HANDLE playcontrol[] = - {state->hUninit, state->hPause, state->hReset, state->hGetvol, - state->hSetvol, state->hPlay, state->hFeed, NULL}; + {state->hUninit, state->hFeed, state->hForceFeed, NULL}; MP_VERBOSE(ao, "Entering dispatch loop!\n"); - while (1) { /* watch events, poll at least every 2 seconds */ - waitstatus = WaitForMultipleObjects(7, playcontrol, FALSE, 2000); + while (1) { /* watch events */ + waitstatus = MsgWaitForMultipleObjects(3, playcontrol, FALSE, INFINITE, + QS_POSTMESSAGE | QS_SENDMESSAGE); switch (waitstatus) { case WAIT_OBJECT_0: /*shutdown*/ - feedwatch = 0; - thread_uninit(state); + wasapi_thread_uninit(state); goto exit_label; - case (WAIT_OBJECT_0 + 1): /* pause */ - feedwatch = 0; - thread_pause(ao); - break; - case (WAIT_OBJECT_0 + 2): /* reset */ - feedwatch = 0; - thread_reset(ao); - break; - case (WAIT_OBJECT_0 + 3): /* getVolume */ - thread_getVol(state); - break; - case (WAIT_OBJECT_0 + 4): /* setVolume */ - thread_setVol(state); - break; - case (WAIT_OBJECT_0 + 5): /* play */ - feedwatch = 0; - thread_resume(ao); + case (WAIT_OBJECT_0 + 1): /* feed */ + thread_feed(ao); break; - case (WAIT_OBJECT_0 + 6): /* feed */ - if (state->is_playing) - feedwatch = 1; + case (WAIT_OBJECT_0 + 2): /* force feed */ thread_feed(ao); + SetEvent(state->hFeedDone); break; - case WAIT_TIMEOUT: /* Did our feed die? */ - if (feedwatch) - return -1; + case (WAIT_OBJECT_0 + 3): /* messages to dispatch (COM marshalling) */ + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + DispatchMessage(&msg); + } break; - default: case WAIT_FAILED: /* ??? */ return -1; } } exit_label: + /* dispatch any possible pending messages */ + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + DispatchMessage(&msg); + } return state->init_ret; } @@ -301,33 +158,21 @@ static void closehandles(struct ao *ao) struct wasapi_state *state = (struct wasapi_state *)ao->priv; if (state->init_done) CloseHandle(state->init_done); - if (state->hPlay) - CloseHandle(state->hPlay); - if (state->hPause) - CloseHandle(state->hPause); - if (state->hReset) - CloseHandle(state->hReset); if (state->hUninit) CloseHandle(state->hUninit); if (state->hFeed) CloseHandle(state->hFeed); - if (state->hGetvol) - CloseHandle(state->hGetvol); - if (state->hSetvol) - CloseHandle(state->hSetvol); - if (state->hDoneVol) - CloseHandle(state->hDoneVol); } static void uninit(struct ao *ao) { MP_VERBOSE(ao, "uninit!\n"); struct wasapi_state *state = (struct wasapi_state *)ao->priv; - state->immed = 1; + wasapi_release_proxies(state); SetEvent(state->hUninit); /* wait up to 10 seconds */ if (WaitForSingleObject(state->threadLoop, 10000) == WAIT_TIMEOUT) - SetEvent(state->fatal_error); + MP_ERR(ao, "audio loop thread refuses to abort!"); if (state->VistaBlob.hAvrt) FreeLibrary(state->VistaBlob.hAvrt); closehandles(ao); @@ -357,18 +202,12 @@ static int init(struct ao *ao) } state->init_done = CreateEventW(NULL, FALSE, FALSE, NULL); - state->hPlay = CreateEventW(NULL, FALSE, FALSE, NULL); /* kick start audio feed */ - state->hPause = CreateEventW(NULL, FALSE, FALSE, NULL); - state->hReset = CreateEventW(NULL, FALSE, FALSE, NULL); - state->hGetvol = CreateEventW(NULL, FALSE, FALSE, NULL); - state->hSetvol = CreateEventW(NULL, FALSE, FALSE, NULL); - state->hDoneVol = CreateEventW(NULL, FALSE, FALSE, NULL); state->hUninit = CreateEventW(NULL, FALSE, FALSE, NULL); - state->fatal_error = CreateEventW(NULL, TRUE, FALSE, NULL); - state->hFeed = CreateEvent(NULL, FALSE, FALSE, NULL); /* for wasapi event mode */ - if (!state->init_done || !state->fatal_error || !state->hPlay || - !state->hPause || !state->hFeed || !state->hReset || !state->hGetvol || - !state->hSetvol || !state->hDoneVol) + state->hFeed = CreateEventW(NULL, FALSE, FALSE, NULL); /* for wasapi event mode */ + state->hForceFeed = CreateEventW(NULL, FALSE, FALSE, NULL); + state->hFeedDone = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!state->init_done || !state->hFeed || !state->hUninit || + !state->hForceFeed || !state->hFeedDone) { closehandles(ao); /* failed to init events */ @@ -388,57 +227,59 @@ static int init(struct ao *ao) } } else MP_VERBOSE(ao, "Init Done!\n"); + + wasapi_setup_proxies(state); return state->init_ret; } static int control(struct ao *ao, enum aocontrol cmd, void *arg) { struct wasapi_state *state = (struct wasapi_state *)ao->priv; - if (!(state->vol_hw_support & ENDPOINT_HARDWARE_SUPPORT_VOLUME)) + if (!state->share_mode && !(state->vol_hw_support & ENDPOINT_HARDWARE_SUPPORT_VOLUME)) { return CONTROL_UNKNOWN; /* hw does not support volume controls in exclusive mode */ + } ao_control_vol_t *vol = (ao_control_vol_t *)arg; - ResetEvent(state->hDoneVol); switch (cmd) { case AOCONTROL_GET_VOLUME: - SetEvent(state->hGetvol); - if (WaitForSingleObject(state->hDoneVol, 100) == WAIT_OBJECT_0) { - vol->left = vol->right = 100.0f * state->audio_volume; - return CONTROL_OK; - } - return CONTROL_UNKNOWN; + IAudioEndpointVolume_GetMasterVolumeLevelScalar(state->pEndpointVolumeProxy, + &state->audio_volume); + vol->left = vol->right = 100.0f * state->audio_volume; + return CONTROL_OK; case AOCONTROL_SET_VOLUME: state->audio_volume = vol->left / 100.f; - SetEvent(state->hSetvol); - if (WaitForSingleObject(state->hDoneVol, 100) == WAIT_OBJECT_0) - return CONTROL_OK; - return CONTROL_UNKNOWN; + IAudioEndpointVolume_SetMasterVolumeLevelScalar(state->pEndpointVolumeProxy, + state->audio_volume, NULL); + return CONTROL_OK; default: return CONTROL_UNKNOWN; } } -static void audio_resume(struct ao *ao) + +static void audio_pause(struct ao *ao) { struct wasapi_state *state = (struct wasapi_state *)ao->priv; - ResetEvent(state->hPause); - ResetEvent(state->hReset); - SetEvent(state->hPlay); + + IAudioClient_Stop(state->pAudioClientProxy); + IAudioClient_Reset(state->pAudioClientProxy); + state->sample_count = 0; + mp_memory_barrier(); } -static void audio_pause(struct ao *ao) +static void audio_resume(struct ao *ao) { struct wasapi_state *state = (struct wasapi_state *)ao->priv; - ResetEvent(state->hPlay); - SetEvent(state->hPause); + + SetEvent(state->hForceFeed); + WaitForSingleObject(state->hFeedDone, INFINITE); + IAudioClient_Start(state->pAudioClientProxy); } -static void reset(struct ao *ao) +static void audio_reset(struct ao *ao) { - struct wasapi_state *state = (struct wasapi_state *)ao->priv; - ResetEvent(state->hPlay); - SetEvent(state->hReset); + audio_pause(ao); } #define OPT_BASE_STRUCT struct wasapi_state @@ -451,8 +292,7 @@ const struct ao_driver audio_out_wasapi = { .control = control, .pause = audio_pause, .resume = audio_resume, - .reset = reset, - .drain = audio_drain, + .reset = audio_reset, .priv_size = sizeof(wasapi_state), .options = (const struct m_option[]) { OPT_FLAG("exclusive", opt_exclusive, 0), diff --git a/audio/out/ao_wasapi.h b/audio/out/ao_wasapi.h index 8df45f042e..a0ce654d4d 100755 --- a/audio/out/ao_wasapi.h +++ b/audio/out/ao_wasapi.h @@ -34,25 +34,11 @@ typedef struct wasapi_state { /* Init phase */ int init_ret; HANDLE init_done; - HANDLE fatal_error; /* signal to indicate unrecoverable error */ int share_mode; - /* Events */ - HANDLE hPause; - - /* Play */ - HANDLE hPlay; - int is_playing; - - /* Reset */ - HANDLE hReset; - - /* uninit */ HANDLE hUninit; - LONG immed; /* volume control */ - HANDLE hGetvol, hSetvol, hDoneVol; DWORD vol_hw_support, status; float audio_volume; @@ -70,10 +56,23 @@ typedef struct wasapi_state { IAudioRenderClient *pRenderClient; IAudioEndpointVolume *pEndpointVolume; HANDLE hFeed; /* wasapi event */ + HANDLE hForceFeed; /* forces writing a buffer (e.g. before audio_resume) */ + HANDLE hFeedDone; /* set only after a hForceFeed */ HANDLE hTask; /* AV thread */ DWORD taskIndex; /* AV task ID */ WAVEFORMATEXTENSIBLE format; + /* WASAPI proxy handles, for Single-Threaded Apartment communication. + One is needed for each object that's accessed by a different thread. */ + IAudioClient *pAudioClientProxy; + IAudioEndpointVolume *pEndpointVolumeProxy; + + /* Streams used to marshal the proxy objects. The thread owning the actual objects + needs to marshal proxy objects into these streams, and the thread that wants the + proxies unmarshals them from here. */ + IStream *sAudioClient; + IStream *sEndpointVolume; + /* WASAPI internal clock information, for estimating delay */ IAudioClock *pAudioClock; UINT64 clock_frequency; /* scale for the "samples" returned by the clock */ @@ -92,4 +91,4 @@ typedef struct wasapi_state { } VistaBlob; } wasapi_state; -#endif
\ No newline at end of file +#endif diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index dc530820ba..feadfc0631 100755 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -20,7 +20,6 @@ #define COBJMACROS 1 #define _WIN32_WINNT 0x600 -#include <process.h> #include <initguid.h> #include <audioclient.h> #include <endpointvolume.h> @@ -29,15 +28,7 @@ #include "audio/out/ao_wasapi_utils.h" -#include "options/m_option.h" -#include "options/m_config.h" #include "audio/format.h" -#include "common/msg.h" -#include "misc/ring.h" -#include "ao.h" -#include "internal.h" -#include "compat/atomics.h" -#include "osdep/timer.h" #define EXIT_ON_ERROR(hres) \ do { if (FAILED(hres)) { goto exit_label; } } while(0) @@ -343,7 +334,7 @@ static int try_passthrough(struct wasapi_state *state, return 0; } -int wasapi_find_formats(struct ao *const ao) +static int find_formats(struct ao *const ao) { struct wasapi_state *state = (struct wasapi_state *)ao->priv; @@ -470,11 +461,10 @@ static int init_clock(struct wasapi_state *state) { exit_label: MP_ERR(state, "init_clock failed with %s, unable to obtain the audio device's timing!\n", wasapi_explain_err(hr)); - SetEvent(state->fatal_error); return 1; } -int wasapi_fix_format(struct wasapi_state *state) +static int fix_format(struct wasapi_state *state) { HRESULT hr; double offset = 0.5; @@ -538,7 +528,6 @@ reinit: exit_label: MP_ERR(state, "fix_format fails with %s, failed to determine buffer block size!\n", wasapi_explain_err(hr)); - SetEvent(state->fatal_error); return 1; } @@ -552,7 +541,7 @@ static char* wstring_to_utf8(wchar_t *wstring) { return NULL; } -char* wasapi_get_device_id(IMMDevice *pDevice) { +static char* get_device_id(IMMDevice *pDevice) { if (!pDevice) { return NULL; } @@ -576,7 +565,7 @@ exit_label: return idstr; } -char* wasapi_get_device_name(IMMDevice *pDevice) { +static char* get_device_name(IMMDevice *pDevice) { if (!pDevice) { return NULL; } @@ -664,7 +653,7 @@ static HRESULT enumerate_with_state(struct mp_log *log, char *header, &pDevice); EXIT_ON_ERROR(hr); - defid = wasapi_get_device_id(pDevice); + defid = get_device_id(pDevice); SAFE_RELEASE(pDevice, IMMDevice_Release(pDevice)); @@ -682,8 +671,8 @@ static HRESULT enumerate_with_state(struct mp_log *log, char *header, hr = IMMDeviceCollection_Item(pDevices, i, &pDevice); EXIT_ON_ERROR(hr); - char *name = wasapi_get_device_name(pDevice); - char *id = wasapi_get_device_id(pDevice); + char *name = get_device_name(pDevice); + char *id = get_device_id(pDevice); char *mark = ""; if (strcmp(id, defid) == 0) @@ -715,7 +704,7 @@ exit_label: int wasapi_enumerate_devices(struct mp_log *log) { HRESULT hr; - CoInitialize(NULL); + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); hr = enumerate_with_state(log, "Active devices:", DEVICE_STATE_ACTIVE, 1); EXIT_ON_ERROR(hr); @@ -730,7 +719,7 @@ exit_label: return 1; } -HRESULT wasapi_find_and_load_device(struct ao *ao, IMMDevice **ppDevice, +static HRESULT find_and_load_device(struct ao *ao, IMMDevice **ppDevice, char *search) { HRESULT hr; @@ -790,7 +779,7 @@ HRESULT wasapi_find_and_load_device(struct ao *ao, IMMDevice **ppDevice, hr = IMMDeviceCollection_Item(pDevices, i, &pTempDevice); EXIT_ON_ERROR(hr); - if (device_id_match(wasapi_get_device_id(pTempDevice), devid)) { + if (device_id_match(get_device_id(pTempDevice), devid)) { hr = IMMDevice_GetId(pTempDevice, &deviceID); EXIT_ON_ERROR(hr); break; @@ -801,12 +790,12 @@ HRESULT wasapi_find_and_load_device(struct ao *ao, IMMDevice **ppDevice, char *name; if (!search_err) { MP_ERR(ao, "multiple matching devices found!\n"); - name = wasapi_get_device_name(prevDevice); + name = get_device_name(prevDevice); MP_ERR(ao, "%s\n", name); free(name); search_err = 1; } - name = wasapi_get_device_name(pTempDevice); + name = get_device_name(pTempDevice); MP_ERR(ao, "%s\n", name); free(name); } @@ -864,4 +853,119 @@ int wasapi_validate_device(struct mp_log *log, const m_option_t *opt, mp_dbg(log, "device=%s %svalid\n", param.start, ret == 1 ? "" : "not "); return ret; -}
\ No newline at end of file +} + +HRESULT wasapi_setup_proxies(struct wasapi_state *state) { + HRESULT hr; + hr = CoGetInterfaceAndReleaseStream(state->sAudioClient, + &IID_IAudioClient, + (void**) &state->pAudioClientProxy); + state->sAudioClient = NULL; + EXIT_ON_ERROR(hr); + + hr = CoGetInterfaceAndReleaseStream(state->sEndpointVolume, + &IID_IAudioEndpointVolume, + (void**) &state->pEndpointVolumeProxy); + state->sEndpointVolume = NULL; + EXIT_ON_ERROR(hr); + +exit_label: + return hr; +} + +void wasapi_release_proxies(wasapi_state *state) { + SAFE_RELEASE(state->pAudioClientProxy, IUnknown_Release(state->pAudioClientProxy)); + SAFE_RELEASE(state->pEndpointVolumeProxy, IUnknown_Release(state->pEndpointVolumeProxy)); +} + +static HRESULT create_proxies(struct wasapi_state *state) { + HRESULT hr; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &state->sAudioClient); + EXIT_ON_ERROR(hr); + hr = CoMarshalInterThreadInterfaceInStream(&IID_IAudioClient, + (IUnknown*) state->pAudioClient, + &state->sAudioClient); + EXIT_ON_ERROR(hr); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &state->sEndpointVolume); + EXIT_ON_ERROR(hr); + hr = CoMarshalInterThreadInterfaceInStream(&IID_IAudioEndpointVolume, + (IUnknown*) state->pEndpointVolume, + &state->sEndpointVolume); +exit_label: + return hr; +} + +int wasapi_thread_init(struct ao *ao) +{ + struct wasapi_state *state = (struct wasapi_state *)ao->priv; + HRESULT hr; + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + if (!state->opt_device) { + IMMDeviceEnumerator *pEnumerator; + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, + &IID_IMMDeviceEnumerator, (void**)&pEnumerator); + EXIT_ON_ERROR(hr); + + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(pEnumerator, + eRender, eConsole, + &state->pDevice); + SAFE_RELEASE(pEnumerator, IMMDeviceEnumerator_Release(pEnumerator)); + + char *id = get_device_id(state->pDevice); + MP_VERBOSE(ao, "default device ID: %s\n", id); + free(id); + } else { + hr = find_and_load_device(ao, &state->pDevice, state->opt_device); + } + EXIT_ON_ERROR(hr); + + char *name = get_device_name(state->pDevice); + MP_VERBOSE(ao, "device loaded: %s\n", name); + free(name); + + hr = IMMDeviceActivator_Activate(state->pDevice, &IID_IAudioClient, + CLSCTX_ALL, NULL, (void **)&state->pAudioClient); + EXIT_ON_ERROR(hr); + + hr = IMMDeviceActivator_Activate(state->pDevice, &IID_IAudioEndpointVolume, + CLSCTX_ALL, NULL, + (void **)&state->pEndpointVolume); + EXIT_ON_ERROR(hr); + IAudioEndpointVolume_QueryHardwareSupport(state->pEndpointVolume, + &state->vol_hw_support); + + state->init_ret = find_formats(ao); /* Probe support formats */ + if (state->init_ret) + goto exit_label; + if (!fix_format(state)) { /* now that we're sure what format to use */ + EXIT_ON_ERROR(create_proxies(state)); + MP_VERBOSE(ao, "thread_init OK!\n"); + SetEvent(state->init_done); + return state->init_ret; + } +exit_label: + state->init_ret = -1; + SetEvent(state->init_done); + return -1; +} + +void wasapi_thread_uninit(wasapi_state *state) +{ + if (state->pAudioClient) + IAudioClient_Stop(state->pAudioClient); + if (state->pRenderClient) + IAudioRenderClient_Release(state->pRenderClient); + if (state->pAudioClock) + IAudioClock_Release(state->pAudioClock); + if (state->pAudioClient) + IAudioClient_Release(state->pAudioClient); + if (state->pDevice) + IMMDevice_Release(state->pDevice); + if (state->hTask) + state->VistaBlob.pAvRevertMmThreadCharacteristics(state->hTask); + CoUninitialize(); + ExitThread(0); +} diff --git a/audio/out/ao_wasapi_utils.h b/audio/out/ao_wasapi_utils.h index eb4b56556f..fdc6e4fb7c 100755 --- a/audio/out/ao_wasapi_utils.h +++ b/audio/out/ao_wasapi_utils.h @@ -20,37 +20,26 @@ #ifndef MP_AO_WASAPI_UTILS_H_ #define MP_AO_WASAPI_UTILS_H_ -#define COBJMACROS 1 -#define _WIN32_WINNT 0x600 - #include "audio/out/ao_wasapi.h" #include "options/m_option.h" -#include "options/m_config.h" -#include "audio/format.h" #include "common/msg.h" -#include "misc/ring.h" #include "ao.h" #include "internal.h" -#include "compat/atomics.h" -#include "osdep/timer.h" int wasapi_fill_VistaBlob(wasapi_state *state); const char *wasapi_explain_err(const HRESULT hr); -char* wasapi_get_device_name(IMMDevice *pDevice); -char* wasapi_get_device_id(IMMDevice *pDevice); - -int wasapi_find_formats(struct ao *const ao); -int wasapi_fix_format(struct wasapi_state *state); - int wasapi_enumerate_devices(struct mp_log *log); -HRESULT wasapi_find_and_load_device(struct ao *ao, IMMDevice **ppDevice, - char *search); - int wasapi_validate_device(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param); -#endif
\ No newline at end of file +int wasapi_thread_init(struct ao *ao); +void wasapi_thread_uninit(wasapi_state *state); + +HRESULT wasapi_setup_proxies(wasapi_state *state); +void wasapi_release_proxies(wasapi_state *state); + +#endif |