Mark Harmstone : winealsa: Return PKEY_AudioEndpoint_PhysicalSpeakers device prop.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Dec 29 15:42:43 CST 2014


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

Author: Mark Harmstone <hellas at burntcomma.com>
Date:   Sat Dec 27 21:34:48 2014 +0000

winealsa: Return PKEY_AudioEndpoint_PhysicalSpeakers device prop.

---

 dlls/mmdevapi/devenum.c      |  3 ++
 dlls/winealsa.drv/mmdevdrv.c | 84 +++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 79 insertions(+), 8 deletions(-)

diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index 56f770a..c140437 100644
--- a/dlls/mmdevapi/devenum.c
+++ b/dlls/mmdevapi/devenum.c
@@ -371,6 +371,9 @@ static MMDevice *MMDevice_Create(WCHAR *name, GUID *id, EDataFlow flow, DWORD st
                 MMDevice_SetPropValue(id, flow, &PKEY_AudioEndpoint_FormFactor, &pv);
             }
 
+            if (flow != eCapture)
+                set_driver_prop_value(id, flow, &PKEY_AudioEndpoint_PhysicalSpeakers);
+
             RegCloseKey(keyprop);
         }
         RegCloseKey(key);
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index 8f93e79..d2fb2d3 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -32,7 +32,10 @@
 #include "wine/unicode.h"
 #include "wine/list.h"
 
+#include "propsys.h"
+#include "initguid.h"
 #include "ole2.h"
+#include "propkey.h"
 #include "mmdeviceapi.h"
 #include "devpkey.h"
 #include "mmsystem.h"
@@ -3912,6 +3915,44 @@ HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
     return S_OK;
 }
 
+static unsigned int alsa_probe_num_speakers(char *name) {
+    snd_pcm_t *handle;
+    snd_pcm_hw_params_t *params;
+    int err;
+    unsigned int max_channels = 0;
+
+    if ((err = snd_pcm_open(&handle, name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
+        WARN("The device \"%s\" failed to open: %d (%s).\n",
+                name, err, snd_strerror(err));
+        return 0;
+    }
+
+    params = HeapAlloc(GetProcessHeap(), 0, snd_pcm_hw_params_sizeof());
+    if (!params) {
+        WARN("Out of memory.\n");
+        snd_pcm_close(handle);
+        return 0;
+    }
+
+    if ((err = snd_pcm_hw_params_any(handle, params)) < 0) {
+        WARN("snd_pcm_hw_params_any failed for \"%s\": %d (%s).\n",
+                name, err, snd_strerror(err));
+        goto exit;
+    }
+
+    if ((err = snd_pcm_hw_params_get_channels_max(params,
+                    &max_channels)) < 0){
+        WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
+        goto exit;
+    }
+
+exit:
+    HeapFree(GetProcessHeap(), 0, params);
+    snd_pcm_close(handle);
+
+    return max_channels;
+}
+
 enum AudioDeviceConnectionType {
     AudioDeviceConnectionType_Unknown = 0,
     AudioDeviceConnectionType_PCI,
@@ -3920,25 +3961,27 @@ enum AudioDeviceConnectionType {
 
 HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARIANT *out)
 {
+    char name[256];
+    EDataFlow flow;
+
     static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
         {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
     };
 
     TRACE("%s, (%s,%u), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out);
 
+    if(!get_alsa_name_by_guid(guid, name, sizeof(name), &flow))
+    {
+        WARN("Unknown interface %s\n", debugstr_guid(guid));
+        return E_NOINTERFACE;
+    }
+
     if(IsEqualPropertyKey(*prop, devicepath_key))
     {
-        char name[256], uevent[MAX_PATH];
-        EDataFlow flow;
+        char uevent[MAX_PATH];
         FILE *fuevent;
         int card, device;
 
-        if(!get_alsa_name_by_guid(guid, name, sizeof(name), &flow))
-        {
-            WARN("Unknown interface %s\n", debugstr_guid(guid));
-            return E_NOINTERFACE;
-        }
-
         /* only implemented for identifiable devices, i.e. not "default" */
         if(!sscanf(name, "plughw:%u,%u", &card, &device))
             return E_NOTIMPL;
@@ -4013,6 +4056,31 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
             WARN("Could not open %s for reading\n", uevent);
             return E_NOTIMPL;
         }
+    } else if (flow != eCapture && IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
+        unsigned int num_speakers, card, device;
+        char hwname[255];
+
+        if (sscanf(name, "plughw:%u,%u", &card, &device))
+            sprintf(hwname, "hw:%u,%u", card, device); /* must be hw rather than plughw to work */
+        else
+            strcpy(hwname, name);
+
+        num_speakers = alsa_probe_num_speakers(hwname);
+        if (num_speakers == 0)
+            return E_FAIL;
+
+        out->vt = VT_UI4;
+
+        if (num_speakers >= 6)
+            out->u.ulVal = KSAUDIO_SPEAKER_5POINT1;
+        else if (num_speakers >= 4)
+            out->u.ulVal = KSAUDIO_SPEAKER_QUAD;
+        else if (num_speakers >= 2)
+            out->u.ulVal = KSAUDIO_SPEAKER_STEREO;
+        else if (num_speakers == 1)
+            out->u.ulVal = KSAUDIO_SPEAKER_MONO;
+
+        return S_OK;
     }
 
     TRACE("Unimplemented property %s,%u\n", wine_dbgstr_guid(&prop->fmtid), prop->pid);




More information about the wine-cvs mailing list