From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/client.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index ed635bcf98a..1058c639ff9 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -140,21 +140,21 @@ static HRESULT adjust_timing(struct audio_client *client, const WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE *)fmt; if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && (fmtex->dwChannelMask == 0 || fmtex->dwChannelMask & SPEAKER_RESERVED)) - hr = AUDCLNT_E_UNSUPPORTED_FORMAT; + return AUDCLNT_E_UNSUPPORTED_FORMAT; else { if (*period == 0) *period = def_period; if (*period < min_period || *period > 5000000) - hr = AUDCLNT_E_INVALID_DEVICE_PERIOD; + return AUDCLNT_E_INVALID_DEVICE_PERIOD; else if (*duration > 20000000) /* The smaller the period, the lower this limit. */ - hr = AUDCLNT_E_BUFFER_SIZE_ERROR; + return AUDCLNT_E_BUFFER_SIZE_ERROR; else if (flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) { if (*duration != *period) - hr = AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL; + return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL;
FIXME("EXCLUSIVE mode with EVENTCALLBACK\n");
- hr = AUDCLNT_E_DEVICE_IN_USE; + return AUDCLNT_E_DEVICE_IN_USE; } else if (*duration < 8 * *period) *duration = 8 * *period; /* May grow above 2s. */ }
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/client.c | 20 +++++++++++++++----- dlls/mmdevapi/mmdevdrv.h | 2 ++ 2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 1058c639ff9..297ce5fa9a2 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -133,7 +133,10 @@ static HRESULT adjust_timing(struct audio_client *client, TRACE("Device periods: %lu default and %lu minimum\n", (ULONG)def_period, (ULONG)min_period);
if (mode == AUDCLNT_SHAREMODE_SHARED) { - *period = def_period; + if (*period == 0 || !client->init_audioclient3) + *period = def_period; + else if (*period < min_period) + return AUDCLNT_E_INVALID_DEVICE_PERIOD; if (*duration < 3 * *period) *duration = 3 * *period; } else { @@ -1018,14 +1021,21 @@ static HRESULT WINAPI client_InitializeSharedAudioStream(IAudioClient3 *iface, D const GUID *session_guid) { struct audio_client *This = impl_from_IAudioClient3(iface); - REFERENCE_TIME duration; - FIXME("(%p)->(0x%lx, %u, %p, %s) - partial stub\n", This, flags, period_frames, format, debugstr_guid(session_guid)); + REFERENCE_TIME period; + HRESULT hr; + + TRACE("(%p)->(0x%lx, %u, %p, %s)\n", This, flags, period_frames, format, debugstr_guid(session_guid));
if (!format) return E_POINTER;
- duration = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec; - return client_Initialize(iface, AUDCLNT_SHAREMODE_SHARED, flags, duration, 0, format, session_guid); + period = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec; + + This->init_audioclient3 = TRUE; + hr = client_Initialize(iface, AUDCLNT_SHAREMODE_SHARED, flags, 0, period, format, session_guid); + This->init_audioclient3 = FALSE; + + return hr; }
const IAudioClient3Vtbl AudioClient3_Vtbl = diff --git a/dlls/mmdevapi/mmdevdrv.h b/dlls/mmdevapi/mmdevdrv.h index 42b01443ff0..7a124151f03 100644 --- a/dlls/mmdevapi/mmdevdrv.h +++ b/dlls/mmdevapi/mmdevdrv.h @@ -69,6 +69,8 @@ struct audio_client { IMMDevice *parent; IUnknown *marshal;
+ BOOLEAN init_audioclient3; + EDataFlow dataflow; float *vols; UINT32 channel_count;
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/client.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 297ce5fa9a2..6517433fe94 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -993,17 +993,28 @@ static HRESULT WINAPI client_GetSharedModeEnginePeriod(IAudioClient3 *iface, UINT32 *max_period_frames) { struct audio_client *This = impl_from_IAudioClient3(iface); - FIXME("(%p)->(%p, %p, %p, %p, %p) - partial stub\n", + REFERENCE_TIME def_period, min_period; + HRESULT hr; + + TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, format, default_period_frames, unit_period_frames, min_period_frames, max_period_frames);
- *default_period_frames = - *min_period_frames = - *max_period_frames = - format->nSamplesPerSec / 100; /* ~10ms */ - *unit_period_frames = 1; - return S_OK; + if (!default_period_frames | !unit_period_frames | !max_period_frames) + return E_INVALIDARG; + if (!min_period_frames) + return E_POINTER; + + if (FAILED(hr = get_periods(This, &def_period, &min_period))) + return hr; + + *default_period_frames = def_period * format->nSamplesPerSec / (REFERENCE_TIME)10000000; + *min_period_frames = min_period * format->nSamplesPerSec / (REFERENCE_TIME)10000000; + *max_period_frames = *default_period_frames; + *unit_period_frames = 1; + + return hr; }
static HRESULT WINAPI client_GetCurrentSharedModeEnginePeriod(IAudioClient3 *iface,
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/client.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 6517433fe94..176e2204031 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -1022,8 +1022,21 @@ static HRESULT WINAPI client_GetCurrentSharedModeEnginePeriod(IAudioClient3 *ifa UINT32 *cur_period_frames) { struct audio_client *This = impl_from_IAudioClient3(iface); - FIXME("(%p)->(%p, %p) - stub\n", This, cur_format, cur_period_frames); - return E_NOTIMPL; + UINT32 var; + HRESULT hr; + + TRACE("(%p)->(%p, %p)\n", This, cur_format, cur_period_frames); + + if (!cur_format || !cur_period_frames) + return E_POINTER; + + if (FAILED(hr = client_GetMixFormat(iface, cur_format))) + return hr; + + if (FAILED(hr = client_GetSharedModeEnginePeriod(iface, *cur_format, cur_period_frames, &var, &var, &var))) + return hr; + + return hr; }
static HRESULT WINAPI client_InitializeSharedAudioStream(IAudioClient3 *iface, DWORD flags,
Davide Beatrici (@davidebeatrici) commented about dlls/mmdevapi/client.c:
*period = def_period; if (*period < min_period || *period > 5000000)
hr = AUDCLNT_E_INVALID_DEVICE_PERIOD;
return AUDCLNT_E_INVALID_DEVICE_PERIOD; else if (*duration > 20000000) /* The smaller the period, the lower this limit. */
hr = AUDCLNT_E_BUFFER_SIZE_ERROR;
return AUDCLNT_E_BUFFER_SIZE_ERROR; else if (flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) { if (*duration != *period)
hr = AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL;
return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL; FIXME("EXCLUSIVE mode with EVENTCALLBACK\n");
hr = AUDCLNT_E_DEVICE_IN_USE;
return AUDCLNT_E_DEVICE_IN_USE;
Technically `AUDCLNT_E_DEVICE_IN_USE` being returned instead of `AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL` could have been considered a bug, but in practice it doesn't matter as we don't support the mode.
Davide Beatrici (@davidebeatrici) commented about dlls/mmdevapi/client.c:
- TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, format, default_period_frames, unit_period_frames, min_period_frames, max_period_frames);
- *default_period_frames =
*min_period_frames =
*max_period_frames =
format->nSamplesPerSec / 100; /* ~10ms */
- *unit_period_frames = 1;
- return S_OK;
- if (!default_period_frames | !unit_period_frames | !max_period_frames)
return E_INVALIDARG;
- if (!min_period_frames)
return E_POINTER;
As silly as it looks, this matches the behavior of a fully updated Windows 11 installation.
Davide Beatrici (@davidebeatrici) commented about dlls/mmdevapi/client.c:
UINT32 *cur_period_frames)
{ struct audio_client *This = impl_from_IAudioClient3(iface);
- FIXME("(%p)->(%p, %p) - stub\n", This, cur_format, cur_period_frames);
- return E_NOTIMPL;
- UINT32 var;
This is a throwaway variable. Is the `var` name okay?
@huw If the changes look good to you I'll write the missing tests.
On Wed Jun 19 03:19:40 2024 +0000, Davide Beatrici wrote:
As silly as it looks, this matches the behavior of a fully updated Windows 11 installation.
Generally, unless there's a app that's known to depend on this, please leave out the param checking.
Huw Davies (@huw) commented about dlls/mmdevapi/client.c:
- FIXME("(%p)->(0x%lx, %u, %p, %s) - partial stub\n", This, flags, period_frames, format, debugstr_guid(session_guid));
REFERENCE_TIME period;
HRESULT hr;
TRACE("(%p)->(0x%lx, %u, %p, %s)\n", This, flags, period_frames, format, debugstr_guid(session_guid));
if (!format) return E_POINTER;
- duration = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec;
- return client_Initialize(iface, AUDCLNT_SHAREMODE_SHARED, flags, duration, 0, format, session_guid);
- period = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec;
- This->init_audioclient3 = TRUE;
- hr = client_Initialize(iface, AUDCLNT_SHAREMODE_SHARED, flags, 0, period, format, session_guid);
- This->init_audioclient3 = FALSE;
This is pretty ugly - please find another way (perhaps using a helper function for client initialisation).
On Wed Jun 19 03:19:40 2024 +0000, Davide Beatrici wrote:
This is a throwaway variable. Is the `var` name okay?
`dummy` would be a better name.