From c8c6cc97bcaab5441ea200041bb7cc99c4ba01fb Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Thu, 20 Oct 2011 15:15:09 -0500 Subject: [PATCH] dsound: Always enumerate the default device first. --- dlls/dsound/dsound_main.c | 92 +++++++++++++++++++++++++------------ dlls/dsound/tests/dsound8.c | 74 +++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 30 deletions(-) diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c index 02edf88dbaa..c5b6dce5416 100644 --- a/dlls/dsound/dsound_main.c +++ b/dlls/dsound/dsound_main.c @@ -478,6 +478,47 @@ HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device) return DSERR_INVALIDPARAM; } +static BOOL send_device(IMMDevice *device, GUID *guid, + LPDSENUMCALLBACKW cb, void *user) +{ + IPropertyStore *ps; + PROPVARIANT pv; + BOOL keep_going; + HRESULT hr; + + PropVariantInit(&pv); + + hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); + if(FAILED(hr)){ + WARN("OpenPropertyStore failed: %08x\n", hr); + return TRUE; + } + + hr = get_mmdevice_guid(device, ps, guid); + if(FAILED(hr)){ + IPropertyStore_Release(ps); + return TRUE; + } + + hr = IPropertyStore_GetValue(ps, + (const PROPERTYKEY *)&DEVPKEY_Device_FriendlyName, &pv); + if(FAILED(hr)){ + IPropertyStore_Release(ps); + WARN("GetValue(FriendlyName) failed: %08x\n", hr); + return TRUE; + } + + TRACE("Calling back with %s (%s)\n", wine_dbgstr_guid(guid), + wine_dbgstr_w(pv.u.pwszVal)); + + keep_going = cb(guid, pv.u.pwszVal, wine_vxd_drv, user); + + PropVariantClear(&pv); + IPropertyStore_Release(ps); + + return keep_going; +} + /* S_FALSE means the callback returned FALSE at some point * S_OK means the callback always returned TRUE */ HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids, @@ -485,7 +526,8 @@ HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids, { IMMDeviceEnumerator *devenum; IMMDeviceCollection *coll; - UINT count, i; + IMMDevice *defdev = NULL; + UINT count, i, n; BOOL keep_going; HRESULT hr; @@ -514,14 +556,24 @@ HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids, if(count == 0) return DS_OK; + TRACE("Calling back with NULL (%s)\n", wine_dbgstr_w(primary_desc)); keep_going = cb(NULL, primary_desc, empty_drv, user); + /* always send the default device first */ + if(keep_going){ + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flow, + eMultimedia, &defdev); + if(FAILED(hr)){ + defdev = NULL; + n = 0; + }else{ + keep_going = send_device(defdev, &guids[0], cb, user); + n = 1; + } + } + for(i = 0; keep_going && i < count; ++i){ IMMDevice *device; - IPropertyStore *ps; - PROPVARIANT pv; - - PropVariantInit(&pv); hr = IMMDeviceCollection_Item(coll, i, &device); if(FAILED(hr)){ @@ -529,36 +581,16 @@ HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids, continue; } - hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); - if(FAILED(hr)){ - IMMDevice_Release(device); - WARN("OpenPropertyStore failed: %08x\n", hr); - continue; + if(device != defdev){ + send_device(device, &guids[n], cb, user); + ++n; } - hr = get_mmdevice_guid(device, ps, &guids[i]); - if(FAILED(hr)){ - IPropertyStore_Release(ps); - IMMDevice_Release(device); - continue; - } - - hr = IPropertyStore_GetValue(ps, - (const PROPERTYKEY *)&DEVPKEY_Device_FriendlyName, &pv); - if(FAILED(hr)){ - IPropertyStore_Release(ps); - IMMDevice_Release(device); - WARN("GetValue(FriendlyName) failed: %08x\n", hr); - continue; - } - - keep_going = cb(&guids[i], pv.u.pwszVal, wine_vxd_drv, user); - - PropVariantClear(&pv); - IPropertyStore_Release(ps); IMMDevice_Release(device); } + if(defdev) + IMMDevice_Release(defdev); IMMDeviceCollection_Release(coll); return (keep_going == TRUE) ? S_OK : S_FALSE; diff --git a/dlls/dsound/tests/dsound8.c b/dlls/dsound/tests/dsound8.c index 9489970f72e..c1e672feb05 100644 --- a/dlls/dsound/tests/dsound8.c +++ b/dlls/dsound/tests/dsound8.c @@ -25,6 +25,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define COBJMACROS +#define NONAMELESSUNION #include #include @@ -35,6 +37,13 @@ #include "ks.h" #include "ksmedia.h" +#include "initguid.h" +#include "wingdi.h" +#include "mmdeviceapi.h" +#include "audioclient.h" +#include "propkey.h" +#include "devpkey.h" + #include "dsound_test.h" static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL; @@ -1043,6 +1052,70 @@ static void test_hw_buffers(void) IDirectSound8_Release(ds); } +static struct { + UINT dev_count; + GUID guid; +} default_info = { 0 }; + +static BOOL WINAPI default_device_cb(GUID *guid, const char *desc, + const char *module, void *user) +{ + trace("guid: %p, desc: %s\n", guid, desc); + if(!guid) + ok(default_info.dev_count == 0, "Got NULL GUID not in first position\n"); + else{ + if(default_info.dev_count == 0){ + ok(IsEqualGUID(guid, &default_info.guid), "Expected default device GUID\n"); + }else{ + ok(!IsEqualGUID(guid, &default_info.guid), "Got default GUID at unexpected location: %u\n", + default_info.dev_count); + } + + /* only count real devices */ + ++default_info.dev_count; + } + + return TRUE; +} + +static void test_first_device(void) +{ + IMMDeviceEnumerator *devenum; + IMMDevice *defdev; + IPropertyStore *ps; + PROPVARIANT pv; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, + CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&devenum); + if(FAILED(hr)){ + win_skip("MMDevAPI is not available, skipping default device test\n"); + return; + } + + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, eRender, + eMultimedia, &defdev); + ok(hr == S_OK, "GetDefaultAudioEndpoint failed: %08x\n", hr); + + hr = IMMDevice_OpenPropertyStore(defdev, STGM_READ, &ps); + ok(hr == S_OK, "OpenPropertyStore failed: %08x\n", hr); + + PropVariantInit(&pv); + + hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_GUID, &pv); + ok(hr == S_OK, "GetValue failed: %08x\n", hr); + + CLSIDFromString(pv.u.pwszVal, &default_info.guid); + + PropVariantClear(&pv); + IPropertyStore_Release(ps); + IMMDevice_Release(defdev); + IMMDeviceEnumerator_Release(devenum); + + hr = pDirectSoundEnumerateA(&default_device_cb, NULL); + ok(hr == S_OK, "DirectSoundEnumerateA failed: %08x\n", hr); +} + START_TEST(dsound8) { HMODULE hDsound; @@ -1062,6 +1135,7 @@ START_TEST(dsound8) IDirectSound8_tests(); dsound8_tests(); test_hw_buffers(); + test_first_device(); } else skip("dsound8 test skipped\n");