Andrew Eikum : dsound: Always enumerate the default device first.

Alexandre Julliard julliard at winehq.org
Fri Oct 21 11:01:59 CDT 2011


Module: wine
Branch: master
Commit: c8c6cc97bcaab5441ea200041bb7cc99c4ba01fb
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c8c6cc97bcaab5441ea200041bb7cc99c4ba01fb

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Thu Oct 20 15:15:09 2011 -0500

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 02edf88..c5b6dce 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;
-        }
-
-        hr = get_mmdevice_guid(device, ps, &guids[i]);
-        if(FAILED(hr)){
-            IPropertyStore_Release(ps);
-            IMMDevice_Release(device);
-            continue;
+        if(device != defdev){
+            send_device(device, &guids[n], cb, user);
+            ++n;
         }
 
-        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 9489970..c1e672f 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 <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");




More information about the wine-cvs mailing list