dsound: Don't launch a separate thread for the mmdevapi enumerator.

This commit is contained in:
Andrew Eikum 2012-01-16 10:44:38 -06:00 committed by Alexandre Julliard
parent 04ab858fef
commit 6d391df4aa
1 changed files with 43 additions and 90 deletions

View File

@ -88,17 +88,6 @@ CRITICAL_SECTION DSOUND_capturers_lock = { &DSOUND_capturers_lock_debug, -1, 0,
GUID DSOUND_renderer_guids[MAXWAVEDRIVERS]; GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
GUID DSOUND_capture_guids[MAXWAVEDRIVERS]; GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
static IMMDeviceEnumerator *g_devenum;
static CRITICAL_SECTION g_devenum_lock;
static CRITICAL_SECTION_DEBUG g_devenum_lock_debug =
{
0, 0, &g_devenum_lock,
{ &g_devenum_lock_debug.ProcessLocksList, &g_devenum_lock_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": g_devenum_lock") }
};
static CRITICAL_SECTION g_devenum_lock = { &g_devenum_lock_debug, -1, 0, 0, 0, 0 };
static HANDLE g_devenum_thread;
WCHAR wine_vxd_drv[] = { 'w','i','n','e','m','m','.','v','x','d', 0 }; WCHAR wine_vxd_drv[] = { 'w','i','n','e','m','m','.','v','x','d', 0 };
/* All default settings, you most likely don't want to touch these, see wiki on UsefulRegistryKeys */ /* All default settings, you most likely don't want to touch these, see wiki on UsefulRegistryKeys */
@ -190,83 +179,29 @@ static const char * get_device_id(LPCGUID pGuid)
return debugstr_guid(pGuid); return debugstr_guid(pGuid);
} }
/* The MMDeviceEnumerator object has to be created & destroyed static HRESULT get_mmdevenum(IMMDeviceEnumerator **devenum)
* from the same thread. */
static DWORD WINAPI devenum_thread_proc(void *arg)
{ {
HANDLE evt = arg; HRESULT hr, init_hr;
HRESULT hr;
MSG msg;
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); init_hr = CoInitialize(NULL);
if(FAILED(hr)){
ERR("CoInitializeEx failed: %08x\n", hr);
return 1;
}
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&g_devenum); CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)devenum);
if(FAILED(hr)){ if(FAILED(hr)){
ERR("CoCreateInstance failed: %08x\n", hr);
CoUninitialize(); CoUninitialize();
return 1; *devenum = NULL;
ERR("CoCreateInstance failed: %08x\n", hr);
return hr;
} }
SetEvent(evt); return init_hr;
PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
while(GetMessageW(&msg, NULL, 0, 0)){
if(msg.hwnd)
DispatchMessageW(&msg);
else
ERR("Unknown message: %04x\n", msg.message);
}
IMMDeviceEnumerator_Release(g_devenum);
g_devenum = NULL;
CoUninitialize();
return 0;
} }
static IMMDeviceEnumerator *get_mmdevenum(void) static void release_mmdevenum(IMMDeviceEnumerator *devenum, HRESULT init_hr)
{ {
HANDLE events[2]; IMMDeviceEnumerator_Release(devenum);
DWORD wait; if(SUCCEEDED(init_hr))
CoUninitialize();
EnterCriticalSection(&g_devenum_lock);
if(g_devenum){
LeaveCriticalSection(&g_devenum_lock);
return g_devenum;
}
events[0] = CreateEventW(NULL, FALSE, FALSE, NULL);
g_devenum_thread = CreateThread(NULL, 0, devenum_thread_proc,
events[0], 0, NULL);
if(!g_devenum_thread){
LeaveCriticalSection(&g_devenum_lock);
CloseHandle(events[0]);
return NULL;
}
events[1] = g_devenum_thread;
wait = WaitForMultipleObjects(2, events, FALSE, INFINITE);
CloseHandle(events[0]);
if(wait != WAIT_OBJECT_0){
if(wait == 1 + WAIT_OBJECT_0){
CloseHandle(g_devenum_thread);
g_devenum_thread = NULL;
}
LeaveCriticalSection(&g_devenum_lock);
return NULL;
}
LeaveCriticalSection(&g_devenum_lock);
return g_devenum;
} }
static HRESULT get_mmdevice_guid(IMMDevice *device, IPropertyStore *ps, static HRESULT get_mmdevice_guid(IMMDevice *device, IPropertyStore *ps,
@ -326,16 +261,16 @@ HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
IMMDeviceEnumerator *devenum; IMMDeviceEnumerator *devenum;
EDataFlow flow = (EDataFlow)-1; EDataFlow flow = (EDataFlow)-1;
ERole role = (ERole)-1; ERole role = (ERole)-1;
HRESULT hr; HRESULT hr, init_hr;
TRACE("(%s,%p)\n", get_device_id(pGuidSrc),pGuidDest); TRACE("(%s,%p)\n", get_device_id(pGuidSrc),pGuidDest);
if(!pGuidSrc || !pGuidDest) if(!pGuidSrc || !pGuidDest)
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
devenum = get_mmdevenum(); init_hr = get_mmdevenum(&devenum);
if(!devenum) if(!devenum)
return DSERR_GENERIC; return init_hr;
if(IsEqualGUID(&DSDEVID_DefaultPlayback, pGuidSrc)){ if(IsEqualGUID(&DSDEVID_DefaultPlayback, pGuidSrc)){
role = eMultimedia; role = eMultimedia;
@ -358,15 +293,20 @@ HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
flow, role, &device); flow, role, &device);
if(FAILED(hr)){ if(FAILED(hr)){
WARN("GetDefaultAudioEndpoint failed: %08x\n", hr); WARN("GetDefaultAudioEndpoint failed: %08x\n", hr);
release_mmdevenum(devenum, init_hr);
return DSERR_NODRIVER; return DSERR_NODRIVER;
} }
hr = get_mmdevice_guid(device, NULL, pGuidDest); hr = get_mmdevice_guid(device, NULL, pGuidDest);
IMMDevice_Release(device); IMMDevice_Release(device);
release_mmdevenum(devenum, init_hr);
return (hr == S_OK) ? DS_OK : hr; return (hr == S_OK) ? DS_OK : hr;
} }
release_mmdevenum(devenum, init_hr);
*pGuidDest = *pGuidSrc; *pGuidDest = *pGuidSrc;
return DS_OK; return DS_OK;
@ -424,22 +364,24 @@ HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device)
IMMDeviceEnumerator *devenum; IMMDeviceEnumerator *devenum;
IMMDeviceCollection *coll; IMMDeviceCollection *coll;
UINT count, i; UINT count, i;
HRESULT hr; HRESULT hr, init_hr;
devenum = get_mmdevenum(); init_hr = get_mmdevenum(&devenum);
if(!devenum) if(!devenum)
return DSERR_GENERIC; return init_hr;
hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flow, hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flow,
DEVICE_STATE_ACTIVE, &coll); DEVICE_STATE_ACTIVE, &coll);
if(FAILED(hr)){ if(FAILED(hr)){
WARN("EnumAudioEndpoints failed: %08x\n", hr); WARN("EnumAudioEndpoints failed: %08x\n", hr);
release_mmdevenum(devenum, init_hr);
return hr; return hr;
} }
hr = IMMDeviceCollection_GetCount(coll, &count); hr = IMMDeviceCollection_GetCount(coll, &count);
if(FAILED(hr)){ if(FAILED(hr)){
IMMDeviceCollection_Release(coll); IMMDeviceCollection_Release(coll);
release_mmdevenum(devenum, init_hr);
WARN("GetCount failed: %08x\n", hr); WARN("GetCount failed: %08x\n", hr);
return hr; return hr;
} }
@ -457,14 +399,20 @@ HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device)
continue; continue;
} }
if(IsEqualGUID(&guid, tgt)) if(IsEqualGUID(&guid, tgt)){
IMMDeviceCollection_Release(coll);
release_mmdevenum(devenum, init_hr);
return DS_OK; return DS_OK;
}
IMMDevice_Release(*device); IMMDevice_Release(*device);
} }
WARN("No device with GUID %s found!\n", wine_dbgstr_guid(tgt)); WARN("No device with GUID %s found!\n", wine_dbgstr_guid(tgt));
IMMDeviceCollection_Release(coll);
release_mmdevenum(devenum, init_hr);
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
@ -519,19 +467,20 @@ HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids,
IMMDevice *defdev = NULL; IMMDevice *defdev = NULL;
UINT count, i, n; UINT count, i, n;
BOOL keep_going; BOOL keep_going;
HRESULT hr; HRESULT hr, init_hr;
static const WCHAR primary_desc[] = {'P','r','i','m','a','r','y',' ', static const WCHAR primary_desc[] = {'P','r','i','m','a','r','y',' ',
'S','o','u','n','d',' ','D','r','i','v','e','r',0}; 'S','o','u','n','d',' ','D','r','i','v','e','r',0};
static const WCHAR empty_drv[] = {0}; static const WCHAR empty_drv[] = {0};
devenum = get_mmdevenum(); init_hr = get_mmdevenum(&devenum);
if(!devenum) if(!devenum)
return DS_OK; return init_hr;
hr = IMMDeviceEnumerator_EnumAudioEndpoints(g_devenum, flow, hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flow,
DEVICE_STATE_ACTIVE, &coll); DEVICE_STATE_ACTIVE, &coll);
if(FAILED(hr)){ if(FAILED(hr)){
release_mmdevenum(devenum, init_hr);
WARN("EnumAudioEndpoints failed: %08x\n", hr); WARN("EnumAudioEndpoints failed: %08x\n", hr);
return DS_OK; return DS_OK;
} }
@ -539,12 +488,15 @@ HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids,
hr = IMMDeviceCollection_GetCount(coll, &count); hr = IMMDeviceCollection_GetCount(coll, &count);
if(FAILED(hr)){ if(FAILED(hr)){
IMMDeviceCollection_Release(coll); IMMDeviceCollection_Release(coll);
release_mmdevenum(devenum, init_hr);
WARN("GetCount failed: %08x\n", hr); WARN("GetCount failed: %08x\n", hr);
return DS_OK; return DS_OK;
} }
if(count == 0) if(count == 0){
release_mmdevenum(devenum, init_hr);
return DS_OK; return DS_OK;
}
TRACE("Calling back with NULL (%s)\n", wine_dbgstr_w(primary_desc)); TRACE("Calling back with NULL (%s)\n", wine_dbgstr_w(primary_desc));
keep_going = cb(NULL, primary_desc, empty_drv, user); keep_going = cb(NULL, primary_desc, empty_drv, user);
@ -583,6 +535,8 @@ HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids,
IMMDevice_Release(defdev); IMMDevice_Release(defdev);
IMMDeviceCollection_Release(coll); IMMDeviceCollection_Release(coll);
release_mmdevenum(devenum, init_hr);
return (keep_going == TRUE) ? S_OK : S_FALSE; return (keep_going == TRUE) ? S_OK : S_FALSE;
} }
@ -862,7 +816,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
TRACE("DLL_PROCESS_DETACH\n"); TRACE("DLL_PROCESS_DETACH\n");
DeleteCriticalSection(&DSOUND_renderers_lock); DeleteCriticalSection(&DSOUND_renderers_lock);
DeleteCriticalSection(&DSOUND_capturers_lock); DeleteCriticalSection(&DSOUND_capturers_lock);
DeleteCriticalSection(&g_devenum_lock);
break; break;
default: default:
TRACE("UNKNOWN REASON\n"); TRACE("UNKNOWN REASON\n");