Required by Cyberpunk 2077 for 4.0 audio setups (`PKEY_AudioEndpoint_PhysicalSpeakers` is `SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT`) as it then dereferences the device path property (`{b3f8fa53-0004-438e-9003-51a46e139bfc},2`) without checking if is is non-NULL.
The patches use `{1}.ROOT\MEDIA%04u` which is used on Windows for virtual audio devices (e.g. the ones created Voicemeeter Banana).
From: Arkadiusz Hiler ahiler@codeweavers.com
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/winepulse.drv/pulse.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 0e504b6b6dd..42d73db45f9 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -2207,27 +2207,26 @@ static BOOL get_device_path(PhysDevice *dev, struct get_prop_value_params *param { const GUID *guid = params->guid; UINT serial_number; - const char *fmt; char path[128]; int len;
+ /* As hardly any audio devices have serial numbers, Windows instead + appears to use a persistent random number. We emulate this here + by instead using the last 8 hex digits of the GUID. */ + serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7]; + switch (dev->bus_type) { case phys_device_bus_pci: - fmt = "{1}.HDAUDIO\FUNC_01&VEN_%04X&DEV_%04X\%u&%08X"; + len = sprintf(path, "{1}.HDAUDIO\FUNC_01&VEN_%04X&DEV_%04X\%u&%08X", dev->vendor_id, dev->product_id, dev->index, serial_number); break; case phys_device_bus_usb: - fmt = "{1}.USB\VID_%04X&PID_%04X\%u&%08X"; + len = sprintf(path, "{1}.USB\VID_%04X&PID_%04X\%u&%08X", dev->vendor_id, dev->product_id, dev->index, serial_number); break; default: - return FALSE; + len = sprintf(path, "{1}.ROOT\MEDIA\%04u", dev->index); + break; }
- /* As hardly any audio devices have serial numbers, Windows instead - appears to use a persistent random number. We emulate this here - by instead using the last 8 hex digits of the GUID. */ - serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7]; - - len = sprintf(path, fmt, dev->vendor_id, dev->product_id, dev->index, serial_number); ntdll_umbstowcs(path, len + 1, params->wstr, ARRAY_SIZE(params->wstr));
params->vt = VT_LPWSTR;
From: Arkadiusz Hiler ahiler@codeweavers.com
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/winealsa.drv/alsa.c | 77 +++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 41 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index b91606603a2..d8daca7dff7 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -2318,21 +2318,21 @@ static NTSTATUS get_prop_value(void *args)
if(IsEqualPropertyKey(*prop, devicepath_key)) { + enum AudioDeviceConnectionType connection = AudioDeviceConnectionType_Unknown; + USHORT vendor_id = 0, product_id = 0; char uevent[MAX_PATH]; - FILE *fuevent; + FILE *fuevent = NULL; int card, device; + UINT serial_number; + char buf[128]; + int len;
- /* only implemented for identifiable devices, i.e. not "default" */ - if(!sscanf(name, "plughw:%u,%u", &card, &device)){ - params->result = E_NOTIMPL; - return STATUS_SUCCESS; + if(sscanf(name, "plughw:%u,%u", &card, &device)){ + sprintf(uevent, "/sys/class/sound/card%u/device/uevent", card); + fuevent = fopen(uevent, "r"); } - sprintf(uevent, "/sys/class/sound/card%u/device/uevent", card); - fuevent = fopen(uevent, "r");
if(fuevent){ - enum AudioDeviceConnectionType connection = AudioDeviceConnectionType_Unknown; - USHORT vendor_id = 0, product_id = 0; char line[256];
while (fgets(line, sizeof(line), fuevent)) { @@ -2365,41 +2365,36 @@ static NTSTATUS get_prop_value(void *args) }
fclose(fuevent); + }
- if(connection == AudioDeviceConnectionType_USB || connection == AudioDeviceConnectionType_PCI){ - UINT serial_number; - char buf[128]; - int len; - - /* As hardly any audio devices have serial numbers, Windows instead - appears to use a persistent random number. We emulate this here - by instead using the last 8 hex digits of the GUID. */ - serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7]; - - if(connection == AudioDeviceConnectionType_USB) - sprintf(buf, "{1}.USB\VID_%04X&PID_%04X\%u&%08X", - vendor_id, product_id, device, serial_number); - else /* AudioDeviceConnectionType_PCI */ - sprintf(buf, "{1}.HDAUDIO\FUNC_01&VEN_%04X&DEV_%04X\%u&%08X", - vendor_id, product_id, device, serial_number); - - len = strlen(buf) + 1; - if(*params->buffer_size < len * sizeof(WCHAR)){ - params->result = E_NOT_SUFFICIENT_BUFFER; - *params->buffer_size = len * sizeof(WCHAR); - return STATUS_SUCCESS; - } - out->vt = VT_LPWSTR; - out->pwszVal = params->buffer; - ntdll_umbstowcs(buf, len, out->pwszVal, len); - params->result = S_OK; - return STATUS_SUCCESS; - } - }else{ - WARN("Could not open %s for reading\n", uevent); - params->result = E_NOTIMPL; + /* As hardly any audio devices have serial numbers, Windows instead + appears to use a persistent random number. We emulate this here + by instead using the last 8 hex digits of the GUID. */ + serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7]; + + if(connection == AudioDeviceConnectionType_USB) + sprintf(buf, "{1}.USB\VID_%04X&PID_%04X\%u&%08X", + vendor_id, product_id, device, serial_number); + else if (connection == AudioDeviceConnectionType_PCI) + sprintf(buf, "{1}.HDAUDIO\FUNC_01&VEN_%04X&DEV_%04X\%u&%08X", + vendor_id, product_id, device, serial_number); + else + { + ERR("name: %s\n", name); + sprintf(buf, "{1}.ROOT\MEDIA\%04u", serial_number & 0x1FF); + } + + len = strlen(buf) + 1; + if(*params->buffer_size < len * sizeof(WCHAR)){ + params->result = E_NOT_SUFFICIENT_BUFFER; + *params->buffer_size = len * sizeof(WCHAR); return STATUS_SUCCESS; } + out->vt = VT_LPWSTR; + out->pwszVal = params->buffer; + ntdll_umbstowcs(buf, len, out->pwszVal, len); + params->result = S_OK; + return STATUS_SUCCESS; } else if (flow != eCapture && IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) { unsigned int num_speakers, card, device; char hwname[255];
Andrew Eikum (@aeikum) commented about dlls/winealsa.drv/alsa.c:
WARN("Could not open %s for reading\n", uevent);
params->result = E_NOTIMPL;
/* As hardly any audio devices have serial numbers, Windows instead
appears to use a persistent random number. We emulate this here
by instead using the last 8 hex digits of the GUID. */
serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7];
if(connection == AudioDeviceConnectionType_USB)
sprintf(buf, "{1}.USB\\VID_%04X&PID_%04X\\%u&%08X",
vendor_id, product_id, device, serial_number);
else if (connection == AudioDeviceConnectionType_PCI)
sprintf(buf, "{1}.HDAUDIO\\FUNC_01&VEN_%04X&DEV_%04X\\%u&%08X",
vendor_id, product_id, device, serial_number);
else
{
ERR("name: %s\n", name);
Is this ERR intentional? If so it should be a bit more descriptive I think.