From cf16191045db5ad2278c43730453405c7935ab29 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Wed, 10 Dec 2014 18:08:41 +0000
Subject: winepulse: return PKEY_AudioEndpoint_PhysicalSpeakers device prop

Changes by Sebastian Lackner <sebastian@fds-team.de>:
  * Rework logic to get all channel masks in pulse_test_connect.
---
 dlls/winepulse.drv/mmdevdrv.c | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index ca60dcb..03cfed5 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -84,11 +84,11 @@ typedef struct _PhysDevice {
     struct list entry;
     GUID guid;
     EndpointFormFactor form;
+    DWORD channel_mask;
     WCHAR device[128];
     WCHAR name[0];
 } PhysDevice;
 
-static UINT g_phys_speakers_mask = 0;
 static struct list g_phys_speakers = LIST_INIT(g_phys_speakers);
 static struct list g_phys_sources = LIST_INIT(g_phys_sources);
 
@@ -731,7 +731,8 @@ static BOOL get_device_path(pa_proplist *p, int index, GUID *guid, WCHAR path[12
     return TRUE;
 }
 
-static void pulse_add_device(struct list *list, GUID *guid, EndpointFormFactor form, WCHAR device[128], const char *name)
+static void pulse_add_device(struct list *list, GUID *guid, EndpointFormFactor form, DWORD channel_mask,
+                             WCHAR device[128], const char *name)
 {
     static const WCHAR emptyW[] = {0};
     int len = MultiByteToWideChar(CP_UNIXCP, 0, name, -1, NULL, 0);
@@ -740,6 +741,7 @@ static void pulse_add_device(struct list *list, GUID *guid, EndpointFormFactor f
         if (dev) {
             dev->guid = *guid;
             dev->form = form;
+            dev->channel_mask = channel_mask;
             strcpyW(dev->device, device ? device : emptyW);
             MultiByteToWideChar(CP_UNIXCP, 0, name, -1, dev->name, len);
             list_add_tail(list, &dev->entry);
@@ -749,19 +751,25 @@ static void pulse_add_device(struct list *list, GUID *guid, EndpointFormFactor f
 
 static void pulse_phys_speakers_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
 {
+    struct list *speaker;
+    DWORD channel_mask;
     WCHAR device[128];
     GUID guid;
 
     if (i) {
+        channel_mask = pulse_channel_map_to_channel_mask(&i->channel_map);
+
         /* For default PulseAudio render device, OR together all of the
          * PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
-        g_phys_speakers_mask |= pulse_channel_map_to_channel_mask(&i->channel_map);
+        speaker = list_head(&g_phys_speakers);
+        if (speaker)
+            LIST_ENTRY(speaker, PhysDevice, entry)->channel_mask |= channel_mask;
 
         if (!get_device_guid(eRender, i->name, &guid))
             CoCreateGuid(&guid);
         if (!get_device_path(i->proplist, i->index, &guid, device))
             device[0] = 0;
-        pulse_add_device(&g_phys_speakers, &guid, Speakers, device, i->description);
+        pulse_add_device(&g_phys_speakers, &guid, Speakers, channel_mask, device, i->description);
     }
 }
 
@@ -777,7 +785,7 @@ static void pulse_phys_sources_cb(pa_context *c, const pa_source_info *i, int eo
             CoCreateGuid(&guid);
         if (!get_device_path(i->proplist, i->index, &guid, device))
             device[0] = 0;
-        pulse_add_device(&g_phys_sources, &guid, form, device, i->description);
+        pulse_add_device(&g_phys_sources, &guid, form, 0, device, i->description);
     }
 }
 
@@ -844,9 +852,8 @@ static HRESULT pulse_test_connect(void)
     pulse_probe_settings(ml, ctx, 1, &pulse_fmt[0]);
     pulse_probe_settings(ml, ctx, 0, &pulse_fmt[1]);
 
-    g_phys_speakers_mask = 0;
-    pulse_add_device(&g_phys_speakers, &pulse_render_guid, Speakers, NULL, "Pulseaudio");
-    pulse_add_device(&g_phys_sources, &pulse_capture_guid, Microphone, NULL, "Pulseaudio");
+    pulse_add_device(&g_phys_speakers, &pulse_render_guid, Speakers, 0, NULL, "Pulseaudio");
+    pulse_add_device(&g_phys_sources, &pulse_capture_guid, Microphone, 0, NULL, "Pulseaudio");
 
     o = pa_context_get_sink_info_list(ctx, &pulse_phys_speakers_cb, NULL);
     if (o) {
@@ -3609,6 +3616,10 @@ static HRESULT pulse_device_get_prop_value(PhysDevice *dev, const PROPERTYKEY *p
         out->vt = VT_UI4;
         out->u.ulVal = dev->form;
         return S_OK;
+    } else if (IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
+        out->vt = VT_UI4;
+        out->u.ulVal = dev->channel_mask;
+        return out->u.ulVal ? S_OK : E_FAIL;
     }
 
     return E_NOTIMPL;
@@ -3620,13 +3631,6 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
 
     TRACE("%s, (%s,%u), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out);
 
-    if (IsEqualGUID(guid, &pulse_render_guid) && IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
-        out->vt = VT_UI4;
-        out->u.ulVal = g_phys_speakers_mask;
-
-        return out->u.ulVal ? S_OK : E_FAIL;
-    }
-
     LIST_FOR_EACH_ENTRY(dev, &g_phys_speakers, PhysDevice, entry) {
         if (IsEqualGUID(guid, &dev->guid))
             return pulse_device_get_prop_value(dev, prop, out);
-- 
2.6.2

