From e103c8cb4a2cf4db84eda3b38ee3e32559d4ecca Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Mon, 29 Dec 2014 22:05:03 +0000 Subject: [PATCH] added patch to expose PKEY_AudioEndpoint_PhysicalSpeakers for Pulse --- ...-PKEY_AudioEndpoint_PhysicalSpeakers.patch | 175 ++++++++++++++++++ .../winepulse-PulseAudio_Support/definition | 1 + 2 files changed, 176 insertions(+) create mode 100644 patches/winepulse-PulseAudio_Support/0033-winepulse-return-PKEY_AudioEndpoint_PhysicalSpeakers.patch diff --git a/patches/winepulse-PulseAudio_Support/0033-winepulse-return-PKEY_AudioEndpoint_PhysicalSpeakers.patch b/patches/winepulse-PulseAudio_Support/0033-winepulse-return-PKEY_AudioEndpoint_PhysicalSpeakers.patch new file mode 100644 index 00000000..eb21704f --- /dev/null +++ b/patches/winepulse-PulseAudio_Support/0033-winepulse-return-PKEY_AudioEndpoint_PhysicalSpeakers.patch @@ -0,0 +1,175 @@ +From 27bc916773e832868d98144bc3fb6c6c5985524d Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/winepulse-PulseAudio_Support/definition b/patches/winepulse-PulseAudio_Support/definition index e0356258..30b85484 100644 --- a/patches/winepulse-PulseAudio_Support/definition +++ b/patches/winepulse-PulseAudio_Support/definition @@ -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