[PATCH 4/6] winepulse: Fixup IsFormatSupported calls
Andrew Eikum
aeikum at codeweavers.com
Mon Nov 2 11:53:12 CST 2015
From: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Includes a fix contributed by DGhost001.
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
dlls/winepulse.drv/mmdevdrv.c | 174 +++++++++++++++++++++++++++++-------------
1 file changed, 120 insertions(+), 54 deletions(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index 35453af..c312f62 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -1144,10 +1144,8 @@ static HRESULT pulse_spec_from_waveformat(ACImpl *This, const WAVEFORMATEX *fmt)
}
}
This->map.channels = fmt->nChannels;
- if (!mask || mask == SPEAKER_ALL)
+ if (!mask || (mask & (SPEAKER_ALL|SPEAKER_RESERVED)))
mask = get_channel_mask(fmt->nChannels);
- else if (mask == ~0U && fmt->nChannels == 1)
- mask = SPEAKER_FRONT_CENTER;
for (j = 0; j < sizeof(pulse_pos_from_wfx)/sizeof(*pulse_pos_from_wfx) && i < fmt->nChannels; ++j) {
if (mask & (1 << j))
This->map.map[i++] = pulse_pos_from_wfx[j];
@@ -1430,79 +1428,147 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
ACImpl *This = impl_from_IAudioClient(iface);
HRESULT hr = S_OK;
WAVEFORMATEX *closest = NULL;
+ BOOL exclusive;
TRACE("(%p)->(%x, %p, %p)\n", This, mode, fmt, out);
- if (!fmt || (mode == AUDCLNT_SHAREMODE_SHARED && !out))
+ if (!fmt)
return E_POINTER;
if (out)
*out = NULL;
- if (mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE)
+
+ if (mode == AUDCLNT_SHAREMODE_EXCLUSIVE) {
+ exclusive = 1;
+ out = NULL;
+ } else if (mode == AUDCLNT_SHAREMODE_SHARED) {
+ exclusive = 0;
+ if (!out)
+ return E_POINTER;
+ } else
return E_INVALIDARG;
- if (mode == AUDCLNT_SHAREMODE_EXCLUSIVE)
- return This->dataflow == eCapture ? AUDCLNT_E_UNSUPPORTED_FORMAT : AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED;
- switch (fmt->wFormatTag) {
- case WAVE_FORMAT_EXTENSIBLE:
- if (fmt->cbSize < sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
- return E_INVALIDARG;
- dump_fmt(fmt);
- break;
- case WAVE_FORMAT_ALAW:
- case WAVE_FORMAT_MULAW:
- case WAVE_FORMAT_IEEE_FLOAT:
- case WAVE_FORMAT_PCM:
- dump_fmt(fmt);
- break;
- default:
- dump_fmt(fmt);
- return AUDCLNT_E_UNSUPPORTED_FORMAT;
- }
+
if (fmt->nChannels == 0)
return AUDCLNT_E_UNSUPPORTED_FORMAT;
+
closest = clone_format(fmt);
- if (!closest) {
- if (out)
- *out = NULL;
+ if (!closest)
return E_OUTOFMEMORY;
- }
- if (fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
- UINT32 mask = 0, i, channels = 0;
+ dump_fmt(fmt);
+
+ switch (fmt->wFormatTag) {
+ case WAVE_FORMAT_EXTENSIBLE: {
WAVEFORMATEXTENSIBLE *ext = (WAVEFORMATEXTENSIBLE*)closest;
- if ((fmt->nChannels > 1 && ext->dwChannelMask == SPEAKER_ALL) ||
- (fmt->nChannels == 1 && ext->dwChannelMask == ~0U)) {
- mask = ext->dwChannelMask;
- channels = fmt->nChannels;
- } else if (ext->dwChannelMask) {
- for (i = 1; !(i & SPEAKER_RESERVED); i <<= 1) {
- if (i & ext->dwChannelMask) {
- mask |= i;
- channels++;
+ if ((fmt->cbSize != sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) &&
+ fmt->cbSize != sizeof(WAVEFORMATEXTENSIBLE)) ||
+ fmt->nBlockAlign != fmt->wBitsPerSample / 8 * fmt->nChannels ||
+ ext->Samples.wValidBitsPerSample > fmt->wBitsPerSample ||
+ fmt->nAvgBytesPerSec != fmt->nBlockAlign * fmt->nSamplesPerSec) {
+ hr = E_INVALIDARG;
+ break;
+ }
+
+ if (exclusive) {
+ UINT32 mask = 0, i, channels = 0;
+
+ if (!(ext->dwChannelMask & (SPEAKER_ALL | SPEAKER_RESERVED))) {
+ for (i = 1; !(i & SPEAKER_RESERVED); i <<= 1) {
+ if (i & ext->dwChannelMask) {
+ mask |= i;
+ channels++;
+ }
}
+
+ if (channels != fmt->nChannels || (ext->dwChannelMask & ~mask)) {
+ hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ break;
+ }
+ } else {
+ hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ break;
+ }
+ }
+
+ if (IsEqualGUID(&ext->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
+ if (fmt->wBitsPerSample != 32) {
+ hr = E_INVALIDARG;
+ break;
+ }
+
+ if (ext->Samples.wValidBitsPerSample != fmt->wBitsPerSample) {
+ hr = S_FALSE;
+ ext->Samples.wValidBitsPerSample = fmt->wBitsPerSample;
+ }
+ } else if (IsEqualGUID(&ext->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
+ if (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8) {
+ hr = E_INVALIDARG;
+ break;
}
- if (channels < fmt->nChannels)
- mask = get_channel_mask(fmt->nChannels);
- } else
- mask = ext->dwChannelMask;
- if (ext->dwChannelMask != mask) {
- ext->dwChannelMask = mask;
- hr = S_FALSE;
+
+ if (ext->Samples.wValidBitsPerSample != fmt->wBitsPerSample &&
+ !(fmt->wBitsPerSample == 32 &&
+ ext->Samples.wValidBitsPerSample == 24)) {
+ hr = S_FALSE;
+ ext->Samples.wValidBitsPerSample = fmt->wBitsPerSample;
+ break;
+ }
+ } else {
+ hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ break;
}
+
+ break;
}
- if (hr == S_OK || !out) {
+ case WAVE_FORMAT_ALAW:
+ case WAVE_FORMAT_MULAW:
+ if (fmt->wBitsPerSample != 8) {
+ hr = E_INVALIDARG;
+ break;
+ }
+ /* Fall-through */
+ case WAVE_FORMAT_IEEE_FLOAT:
+ if (fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT && fmt->wBitsPerSample != 32) {
+ hr = E_INVALIDARG;
+ break;
+ }
+ /* Fall-through */
+ case WAVE_FORMAT_PCM:
+ if (fmt->wFormatTag == WAVE_FORMAT_PCM &&
+ (!fmt->wBitsPerSample || fmt->wBitsPerSample > 32 || fmt->wBitsPerSample % 8)) {
+ hr = E_INVALIDARG;
+ break;
+ }
+
+ if (fmt->nChannels > 2) {
+ hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ break;
+ }
+ /*
+ * fmt->cbSize, fmt->nBlockAlign and fmt->nAvgBytesPerSec seem to be
+ * ignored, invalid values are happily accepted.
+ */
+ break;
+ default:
+ hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ break;
+ }
+
+ if (exclusive && hr != S_OK) {
+ hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
+ CoTaskMemFree(closest);
+ } else if (hr != S_FALSE)
CoTaskMemFree(closest);
- if (out)
- *out = NULL;
- } else if (closest) {
- closest->nBlockAlign =
- closest->nChannels * closest->wBitsPerSample / 8;
- closest->nAvgBytesPerSec =
- closest->nBlockAlign * closest->nSamplesPerSec;
+ else
*out = closest;
- }
+
+ /* Winepulse does not currently support exclusive mode, if you know of an
+ * application that uses it, I will correct this..
+ */
+ if (hr == S_OK && exclusive)
+ return This->dataflow == eCapture ? AUDCLNT_E_UNSUPPORTED_FORMAT : AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED;
TRACE("returning: %08x %p\n", hr, out ? *out : NULL);
return hr;
--
2.6.2
More information about the wine-patches
mailing list