Merge pull request #211 (Added patch to implement support for GetPropValue to PulseAudio backend.)

This commit is contained in:
Sebastian Lackner 2014-12-06 01:11:01 +01:00
commit f8befaf7fa
5 changed files with 196 additions and 1 deletions

View File

@ -37,8 +37,9 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
===================================
**Bugfixes and features included in the next upcoming release [3]:**
**Bugfixes and features included in the next upcoming release [4]:**
* Add support for GetPropValue to PulseAudio backend
* Fix condition mask handling in RtlVerifyVersionInfo ([Wine Bug #36143](https://bugs.winehq.org/show_bug.cgi?id=36143))
* Fix possible segfault in pulse_rd_loop of PulseAudio backend
* Set last error when GetRawInputDeviceList fails ([Wine Bug #37667](https://bugs.winehq.org/show_bug.cgi?id=37667))

1
debian/changelog vendored
View File

@ -3,6 +3,7 @@ wine-compholio (1.7.33) UNRELEASED; urgency=low
* Added patch to fix condition handling in RtlVerifyVersionInfo.
* Added patch to set last error when GetRawInputDeviceList fails.
* Added patch to fix possible segfault in pulse_rd_loop of PulseAudio backend.
* Added patch to implement support for GetPropValue to PulseAudio backend.
* Removed patch to fix copy and paste errors in ws2_32 tests (accepted upstream).
* Removed patch to fix ordering of IP addresses by metric if two addresses have the same metric (accepted upstream).
* Removed patch to reset data->pWintrustData->u.pFile->hFile after closing handle (accepted upstream).

View File

@ -1816,6 +1816,7 @@ winepulse-PulseAudio_Support.ok:
$(call APPLY_FILE,winepulse-PulseAudio_Support/0028-winepulse-expose-audio-devices-directly-to-programs.patch)
$(call APPLY_FILE,winepulse-PulseAudio_Support/0029-winepulse-implement-exclusive-mode.patch)
$(call APPLY_FILE,winepulse-PulseAudio_Support/0030-winepulse-fix-segfault-in-pulse_rd_loop.patch)
$(call APPLY_FILE,winepulse-PulseAudio_Support/0031-winepulse-implement-GetPropValue.patch)
@( \
echo '+ { "Maarten Lankhorst", "winmm: Load winealsa if winepulse is found.", 1 },'; \
echo '+ { "Maarten Lankhorst", "winepulse: Add initial stub for pulseaudio support.", 1 },'; \
@ -1847,6 +1848,7 @@ winepulse-PulseAudio_Support.ok:
echo '+ { "Mark Harmstone", "winepulse: expose audio devices directly to programs.", 1 },'; \
echo '+ { "Mark Harmstone", "winepulse: implement exclusive mode.", 1 },'; \
echo '+ { "Mark Harmstone", "winepulse: fix segfault in pulse_rd_loop.", 1 },'; \
echo '+ { "Mark Harmstone", "winepulse: implement GetPropValue.", 1 },'; \
) > winepulse-PulseAudio_Support.ok
# Patchset winex11-CandidateWindowPos

View File

@ -0,0 +1,190 @@
From b6c4b15d71542a567f6ca67fe4d0463b04c5fedc Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Thu, 4 Dec 2014 21:36:42 +0000
Subject: [PATCH] winepulse: implement GetPropValue
---
dlls/winepulse.drv/mmdevdrv.c | 153 ++++++++++++++++++++++++++++++++++
dlls/winepulse.drv/winepulse.drv.spec | 1 +
2 files changed, 154 insertions(+)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index 37ff7ee..3acbca5 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -52,6 +52,7 @@
#include "initguid.h"
#include "ks.h"
#include "ksmedia.h"
+#include "propkey.h"
#include "mmdeviceapi.h"
#include "audioclient.h"
#include "endpointvolume.h"
@@ -3430,3 +3431,155 @@ HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
*out = &This->IAudioSessionManager2_iface;
return S_OK;
}
+
+enum AudioDeviceConnectionType {
+ AudioDeviceConnectionType_Unknown = 0,
+ AudioDeviceConnectionType_PCI,
+ AudioDeviceConnectionType_USB
+};
+
+static HRESULT pulse_set_device_path(pa_proplist *p, int index, GUID *guid, PROPVARIANT *pv)
+{
+ const char *buffer;
+ enum AudioDeviceConnectionType connection;
+ USHORT vendor_id, product_id;
+ UINT serial_number;
+
+ static const WCHAR usbformatW[] = { '{','1','}','.','U','S','B','\\','V','I','D','_',
+ '%','0','4','X','&','P','I','D','_','%','0','4','X','\\',
+ '%','u','&','%','0','8','X',0 }; /* "{1}.USB\VID_%04X&PID_%04X\%u&%08X" */
+ static const WCHAR pciformatW[] = { '{','1','}','.','H','D','A','U','D','I','O','\\','F','U','N','C','_','0','1','&',
+ 'V','E','N','_','%','0','4','X','&','D','E','V','_',
+ '%','0','4','X','\\','%','u','&','%','0','8','X',0 }; /* "{1}.HDAUDIO\FUNC_01&VEN_%04X&DEV_%04X\%u&%08X" */
+
+ buffer = pa_proplist_gets(p, PA_PROP_DEVICE_BUS);
+
+ connection = AudioDeviceConnectionType_Unknown;
+ if (buffer) {
+ if (!strcmp(buffer,"pci"))
+ connection = AudioDeviceConnectionType_PCI;
+ else if (!strcmp(buffer,"usb"))
+ connection = AudioDeviceConnectionType_USB;
+ }
+
+ if (connection == AudioDeviceConnectionType_Unknown)
+ return E_FAIL;
+
+ buffer = pa_proplist_gets(p, PA_PROP_DEVICE_VENDOR_ID);
+ if (buffer)
+ vendor_id = strtol(buffer, NULL, 16);
+ else
+ return E_FAIL;
+
+ buffer = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_ID);
+ if (buffer)
+ product_id = strtol(buffer, NULL, 16);
+ else
+ return E_FAIL;
+
+ /* 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];
+
+ pv->vt = VT_LPWSTR;
+ pv->u.pwszVal = CoTaskMemAlloc(128 * sizeof(WCHAR));
+
+ if (!pv->u.pwszVal)
+ return E_OUTOFMEMORY;
+
+ if (connection == AudioDeviceConnectionType_USB)
+ sprintfW( pv->u.pwszVal, usbformatW, vendor_id, product_id, index, serial_number);
+ else if (connection == AudioDeviceConnectionType_PCI)
+ sprintfW( pv->u.pwszVal, pciformatW, vendor_id, product_id, index, serial_number);
+
+ return S_OK;
+}
+
+typedef struct {
+ const PROPERTYKEY *prop;
+ PROPVARIANT *pv;
+ GUID *guid;
+ HRESULT hr;
+} pulse_prop_values_info_cb_data;
+
+static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
+ {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
+};
+
+static void pulse_prop_values_sink_info_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
+{
+ pulse_prop_values_info_cb_data *st = (pulse_prop_values_info_cb_data*)userdata;
+
+ if (!i)
+ return;
+
+ if (IsEqualPropertyKey(*st->prop, devicepath_key))
+ st->hr = pulse_set_device_path(i->proplist, i->index, st->guid, st->pv);
+ else if (IsEqualPropertyKey(*st->prop, PKEY_AudioEndpoint_FormFactor)) {
+ st->pv->vt = VT_UI4;
+ st->pv->u.ulVal = Speakers;
+
+ st->hr = S_OK;
+ } else
+ st->hr = E_NOTIMPL;
+}
+
+static void pulse_prop_values_source_info_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata)
+{
+ pulse_prop_values_info_cb_data *st = (pulse_prop_values_info_cb_data*)userdata;
+
+ if (!i)
+ return;
+
+ if (IsEqualPropertyKey(*st->prop, devicepath_key)) {
+ st->hr = pulse_set_device_path(i->proplist, i->index, st->guid, st->pv);
+ } else if (IsEqualPropertyKey(*st->prop, PKEY_AudioEndpoint_FormFactor)) {
+ st->pv->vt = VT_UI4;
+ st->pv->u.ulVal = (i->monitor_of_sink == PA_INVALID_INDEX) ? Microphone : LineLevel;
+
+ st->hr = S_OK;
+ } else
+ st->hr = E_NOTIMPL;
+}
+
+HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARIANT *out)
+{
+ char name[256];
+ EDataFlow flow;
+ pulse_prop_values_info_cb_data userdata;
+ pa_operation *o;
+
+ TRACE("%s, (%s,%u), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out);
+
+ if (IsEqualGUID(guid, &pulse_render_guid) || IsEqualGUID(guid, &pulse_capture_guid))
+ return E_NOTIMPL;
+
+ if (!get_pulse_name_by_guid(guid, name, sizeof(name), &flow)) {
+ WARN("Unknown interface %s\n", debugstr_guid(guid));
+ return E_NOINTERFACE;
+ }
+
+ if (!IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_FormFactor) &&
+ !IsEqualPropertyKey(*prop, devicepath_key)) {
+ return E_NOTIMPL;
+ }
+
+ userdata.prop = prop;
+ userdata.pv = out;
+ userdata.guid = guid;
+ userdata.hr = E_FAIL;
+
+ if (flow == eRender)
+ o = pa_context_get_sink_info_by_name(pulse_ctx, name, &pulse_prop_values_sink_info_cb, &userdata);
+ else
+ o = pa_context_get_source_info_by_name(pulse_ctx, name, &pulse_prop_values_source_info_cb, &userdata);
+
+ if (!o)
+ return E_FAIL;
+
+ while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) { }
+ pa_operation_unref(o);
+
+ return userdata.hr;
+}
diff --git a/dlls/winepulse.drv/winepulse.drv.spec b/dlls/winepulse.drv/winepulse.drv.spec
index 612bf46..adda949 100644
--- a/dlls/winepulse.drv/winepulse.drv.spec
+++ b/dlls/winepulse.drv/winepulse.drv.spec
@@ -3,3 +3,4 @@
@ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs
@ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint
@ stdcall -private GetAudioSessionManager(ptr ptr) AUDDRV_GetAudioSessionManager
+@ stdcall -private GetPropValue(ptr ptr ptr) AUDDRV_GetPropValue
--
2.0.4

View File

@ -2,3 +2,4 @@ Fixes: [10495] Support for PulseAudio backend for audio
Fixes: Allow selection of audio device for PulseAudio backend
Fixes: [37042] Implement exclusive mode in PulseAudio backend
Fixes: Fix possible segfault in pulse_rd_loop of PulseAudio backend
Fixes: Add support for GetPropValue to PulseAudio backend