dsound: Always enumerate the default device first.

This commit is contained in:
Andrew Eikum 2011-10-20 15:15:09 -05:00 committed by Alexandre Julliard
parent f05a8f89f4
commit c8c6cc97bc
2 changed files with 136 additions and 30 deletions

View File

@ -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;

View File

@ -25,6 +25,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#define NONAMELESSUNION
#include <windows.h>
#include <stdio.h>
@ -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");