added patch to expose PKEY_AudioEndpoint_PhysicalSpeakers for Pulse

This commit is contained in:
Mark Harmstone 2014-12-29 22:05:03 +00:00
parent ca871ef7fd
commit e103c8cb4a
2 changed files with 176 additions and 0 deletions

View File

@ -0,0 +1,175 @@
From 27bc916773e832868d98144bc3fb6c6c5985524d Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Wed, 10 Dec 2014 18:08:41 +0000
Subject: [PATCH 20/20] winepulse: return PKEY_AudioEndpoint_PhysicalSpeakers
device prop
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/winepulse.drv/mmdevdrv.c | 96 ++++++++++++++++++++++++++++++++-----------
1 file changed, 72 insertions(+), 24 deletions(-)
--------------2.0.5
Content-Type: text/x-patch; name="0020-winepulse-return-PKEY_AudioEndpoint_PhysicalSpeakers.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0020-winepulse-return-PKEY_AudioEndpoint_PhysicalSpeakers.patch"
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index 002587f..ff5f58a 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -321,13 +321,44 @@ static const enum pa_channel_position pulse_pos_from_wfx[] = {
PA_CHANNEL_POSITION_TOP_REAR_RIGHT
};
+static DWORD pulse_channel_map_to_channel_mask(const pa_channel_map *map) {
+ int i;
+ DWORD mask = 0;
+
+ for (i = 0; i < map->channels; ++i)
+ switch (map->map[i]) {
+ default: FIXME("Unhandled channel %s\n", pa_channel_position_to_string(map->map[i])); break;
+ case PA_CHANNEL_POSITION_FRONT_LEFT: mask |= SPEAKER_FRONT_LEFT; break;
+ case PA_CHANNEL_POSITION_MONO:
+ case PA_CHANNEL_POSITION_FRONT_CENTER: mask |= SPEAKER_FRONT_CENTER; break;
+ case PA_CHANNEL_POSITION_FRONT_RIGHT: mask |= SPEAKER_FRONT_RIGHT; break;
+ case PA_CHANNEL_POSITION_REAR_LEFT: mask |= SPEAKER_BACK_LEFT; break;
+ case PA_CHANNEL_POSITION_REAR_CENTER: mask |= SPEAKER_BACK_CENTER; break;
+ case PA_CHANNEL_POSITION_REAR_RIGHT: mask |= SPEAKER_BACK_RIGHT; break;
+ case PA_CHANNEL_POSITION_LFE: mask |= SPEAKER_LOW_FREQUENCY; break;
+ case PA_CHANNEL_POSITION_SIDE_LEFT: mask |= SPEAKER_SIDE_LEFT; break;
+ case PA_CHANNEL_POSITION_SIDE_RIGHT: mask |= SPEAKER_SIDE_RIGHT; break;
+ case PA_CHANNEL_POSITION_TOP_CENTER: mask |= SPEAKER_TOP_CENTER; break;
+ case PA_CHANNEL_POSITION_TOP_FRONT_LEFT: mask |= SPEAKER_TOP_FRONT_LEFT; break;
+ case PA_CHANNEL_POSITION_TOP_FRONT_CENTER: mask |= SPEAKER_TOP_FRONT_CENTER; break;
+ case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: mask |= SPEAKER_TOP_FRONT_RIGHT; break;
+ case PA_CHANNEL_POSITION_TOP_REAR_LEFT: mask |= SPEAKER_TOP_BACK_LEFT; break;
+ case PA_CHANNEL_POSITION_TOP_REAR_CENTER: mask |= SPEAKER_TOP_BACK_CENTER; break;
+ case PA_CHANNEL_POSITION_TOP_REAR_RIGHT: mask |= SPEAKER_TOP_BACK_RIGHT; break;
+ case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: mask |= SPEAKER_FRONT_LEFT_OF_CENTER; break;
+ case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: mask |= SPEAKER_FRONT_RIGHT_OF_CENTER; break;
+ }
+
+ return mask;
+}
+
static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt) {
WAVEFORMATEX *wfx = &fmt->Format;
pa_stream *stream;
pa_channel_map map;
pa_sample_spec ss;
pa_buffer_attr attr;
- int ret, i;
+ int ret;
unsigned int length = 0;
pa_channel_map_init_auto(&map, 2, PA_CHANNEL_MAP_ALSA);
@@ -390,28 +421,7 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt) {
else
fmt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- fmt->dwChannelMask = 0;
- for (i = 0; i < map.channels; ++i)
- switch (map.map[i]) {
- default: FIXME("Unhandled channel %s\n", pa_channel_position_to_string(map.map[i])); break;
- case PA_CHANNEL_POSITION_FRONT_LEFT: fmt->dwChannelMask |= SPEAKER_FRONT_LEFT; break;
- case PA_CHANNEL_POSITION_MONO:
- case PA_CHANNEL_POSITION_FRONT_CENTER: fmt->dwChannelMask |= SPEAKER_FRONT_CENTER; break;
- case PA_CHANNEL_POSITION_FRONT_RIGHT: fmt->dwChannelMask |= SPEAKER_FRONT_RIGHT; break;
- case PA_CHANNEL_POSITION_REAR_LEFT: fmt->dwChannelMask |= SPEAKER_BACK_LEFT; break;
- case PA_CHANNEL_POSITION_REAR_CENTER: fmt->dwChannelMask |= SPEAKER_BACK_CENTER; break;
- case PA_CHANNEL_POSITION_REAR_RIGHT: fmt->dwChannelMask |= SPEAKER_BACK_RIGHT; break;
- case PA_CHANNEL_POSITION_LFE: fmt->dwChannelMask |= SPEAKER_LOW_FREQUENCY; break;
- case PA_CHANNEL_POSITION_SIDE_LEFT: fmt->dwChannelMask |= SPEAKER_SIDE_LEFT; break;
- case PA_CHANNEL_POSITION_SIDE_RIGHT: fmt->dwChannelMask |= SPEAKER_SIDE_RIGHT; break;
- case PA_CHANNEL_POSITION_TOP_CENTER: fmt->dwChannelMask |= SPEAKER_TOP_CENTER; break;
- case PA_CHANNEL_POSITION_TOP_FRONT_LEFT: fmt->dwChannelMask |= SPEAKER_TOP_FRONT_LEFT; break;
- case PA_CHANNEL_POSITION_TOP_FRONT_CENTER: fmt->dwChannelMask |= SPEAKER_TOP_FRONT_CENTER; break;
- case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: fmt->dwChannelMask |= SPEAKER_TOP_FRONT_RIGHT; break;
- case PA_CHANNEL_POSITION_TOP_REAR_LEFT: fmt->dwChannelMask |= SPEAKER_TOP_BACK_LEFT; break;
- case PA_CHANNEL_POSITION_TOP_REAR_CENTER: fmt->dwChannelMask |= SPEAKER_TOP_BACK_CENTER; break;
- case PA_CHANNEL_POSITION_TOP_REAR_RIGHT: fmt->dwChannelMask |= SPEAKER_TOP_BACK_RIGHT; break;
- }
+ fmt->dwChannelMask = pulse_channel_map_to_channel_mask(&map);
}
static HRESULT pulse_connect(void)
@@ -3524,6 +3534,10 @@ static void pulse_prop_values_sink_info_cb(pa_context *c, const pa_sink_info *i,
st->pv->vt = VT_UI4;
st->pv->u.ulVal = Speakers;
st->hr = S_OK;
+ } else if (IsEqualPropertyKey(*st->prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
+ st->pv->vt = VT_UI4;
+ st->pv->u.ulVal = pulse_channel_map_to_channel_mask(&i->channel_map);
+ st->hr = S_OK;
} else
st->hr = E_NOTIMPL;
}
@@ -3550,6 +3564,16 @@ static void pulse_prop_values_source_info_cb(pa_context *c, const pa_source_info
pthread_cond_signal(&pulse_cond);
}
+static void pulse_phys_speakers_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
+{
+ PROPVARIANT *pv = userdata;
+
+ if (i)
+ pv->u.ulVal |= pulse_channel_map_to_channel_mask(&i->channel_map);
+
+ pthread_cond_signal(&pulse_cond);
+}
+
HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARIANT *out)
{
struct pulse_prop_values_info_cb_data userdata;
@@ -3559,6 +3583,29 @@ 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)) {
+ /* For default Pulseaudio render device, OR together all of the
+ * PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
+
+ out->vt = VT_UI4;
+ out->u.ulVal = 0;
+
+ pthread_mutex_lock(&pulse_lock);
+ o = pa_context_get_sink_info_list(pulse_ctx, &pulse_phys_speakers_cb, out);
+ if (o) {
+ while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
+ pthread_cond_wait(&pulse_cond, &pulse_lock);
+ pa_operation_unref(o);
+ } else {
+ pthread_mutex_unlock(&pulse_lock);
+ return E_FAIL;
+ }
+
+ pthread_mutex_unlock(&pulse_lock);
+
+ return S_OK;
+ }
+
if (IsEqualGUID(guid, &pulse_render_guid) || IsEqualGUID(guid, &pulse_capture_guid))
return E_NOTIMPL;
@@ -3568,7 +3615,8 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
}
if (!IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_FormFactor) &&
- !IsEqualPropertyKey(*prop, devicepath_key)) {
+ !IsEqualPropertyKey(*prop, devicepath_key) &&
+ (flow == eCapture || !IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers))) {
return E_NOTIMPL;
}
--------------2.0.5--

View File

@ -4,3 +4,4 @@ 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
Fixes: Use actual program name if available to describe PulseAudio streams
Fixes: Expose PKEY_AudioEndpoint_PhysicalSpeakers device property