-- v3: mmdevapi: Implement IAudioClient3_GetCurrentSharedModeEnginePeriod. mmdevapi: Complete IAudioClient3_GetSharedModeEnginePeriod. mmdevapi: Complete IAudioClient3_InitializeSharedAudioStream. mmdevapi: Introduce helper stream_init(). mmdevapi: Return errors early in adjust_timing().
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 | 183 +++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 87 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 1058c639ff9..7a141f03e19 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -355,6 +355,100 @@ skip: return wcsdup(name); }
+static HRESULT stream_init(struct audio_client *client, + const AUDCLNT_SHAREMODE mode, const DWORD flags, + REFERENCE_TIME duration, REFERENCE_TIME period, + const WAVEFORMATEX *fmt, const GUID *sessionguid) +{ + struct create_stream_params params; + UINT32 i, channel_count; + stream_handle stream; + WCHAR *name; + + if (!fmt) + return E_POINTER; + + dump_fmt(fmt); + + if (mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) + return E_INVALIDARG; + + if (flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS | + AUDCLNT_STREAMFLAGS_LOOPBACK | + AUDCLNT_STREAMFLAGS_EVENTCALLBACK | + AUDCLNT_STREAMFLAGS_NOPERSIST | + AUDCLNT_STREAMFLAGS_RATEADJUST | + AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED | + AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE | + AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED | + AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY | + AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM)) { + FIXME("Unknown flags: %08lx\n", flags); + return E_INVALIDARG; + } + + if (FAILED(params.result = adjust_timing(client, &duration, &period, mode, flags, fmt))) + return params.result; + + sessions_lock(); + + if (client->stream) { + sessions_unlock(); + return AUDCLNT_E_ALREADY_INITIALIZED; + } + + if (FAILED(params.result = main_loop_start())) { + sessions_unlock(); + return params.result; + } + + params.name = name = get_application_name(); + params.device = client->device_name; + params.flow = client->dataflow; + params.share = mode; + params.flags = flags; + params.duration = duration; + params.period = period; + params.fmt = fmt; + params.channel_count = &channel_count; + params.stream = &stream; + + wine_unix_call(create_stream, ¶ms); + + free(name); + + if (FAILED(params.result)) { + sessions_unlock(); + return params.result; + } + + if (!(client->vols = malloc(channel_count * sizeof(*client->vols)))) { + params.result = E_OUTOFMEMORY; + goto exit; + } + + for (i = 0; i < channel_count; i++) + client->vols[i] = 1.f; + + params.result = get_audio_session(sessionguid, client->parent, channel_count, &client->session); + +exit: + if (FAILED(params.result)) { + stream_release(stream, NULL); + free(client->vols); + client->vols = NULL; + } else { + list_add_tail(&client->session->clients, &client->entry); + client->stream = stream; + client->channel_count = channel_count; + set_stream_volumes(client); + } + + sessions_unlock(); + + return params.result; +} + static HRESULT WINAPI capture_QueryInterface(IAudioCaptureClient *iface, REFIID riid, void **ppv) { struct audio_client *This = impl_from_IAudioCaptureClient(iface); @@ -537,97 +631,12 @@ static HRESULT WINAPI client_Initialize(IAudioClient3 *iface, AUDCLNT_SHAREMODE const WAVEFORMATEX *fmt, const GUID *sessionguid) { struct audio_client *This = impl_from_IAudioClient3(iface); - struct create_stream_params params; - UINT32 i, channel_count; - stream_handle stream; - WCHAR *name;
TRACE("(%p)->(%x, %lx, %s, %s, %p, %s)\n", This, mode, flags, wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
- if (!fmt) - return E_POINTER; - - dump_fmt(fmt); - - if (mode != AUDCLNT_SHAREMODE_SHARED && mode != AUDCLNT_SHAREMODE_EXCLUSIVE) - return E_INVALIDARG; - - if (flags & ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS | - AUDCLNT_STREAMFLAGS_LOOPBACK | - AUDCLNT_STREAMFLAGS_EVENTCALLBACK | - AUDCLNT_STREAMFLAGS_NOPERSIST | - AUDCLNT_STREAMFLAGS_RATEADJUST | - AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED | - AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE | - AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED | - AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY | - AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM)) { - FIXME("Unknown flags: %08lx\n", flags); - return E_INVALIDARG; - } - - if (FAILED(params.result = adjust_timing(This, &duration, &period, mode, flags, fmt))) - return params.result; - - sessions_lock(); - - if (This->stream) { - sessions_unlock(); - return AUDCLNT_E_ALREADY_INITIALIZED; - } - - if (FAILED(params.result = main_loop_start())) { - sessions_unlock(); - return params.result; - } - - params.name = name = get_application_name(); - params.device = This->device_name; - params.flow = This->dataflow; - params.share = mode; - params.flags = flags; - params.duration = duration; - params.period = period; - params.fmt = fmt; - params.channel_count = &channel_count; - params.stream = &stream; - - wine_unix_call(create_stream, ¶ms); - - free(name); - - if (FAILED(params.result)) { - sessions_unlock(); - return params.result; - } - - if (!(This->vols = malloc(channel_count * sizeof(*This->vols)))) { - params.result = E_OUTOFMEMORY; - goto exit; - } - - for (i = 0; i < channel_count; i++) - This->vols[i] = 1.f; - - params.result = get_audio_session(sessionguid, This->parent, channel_count, &This->session); - -exit: - if (FAILED(params.result)) { - stream_release(stream, NULL); - free(This->vols); - This->vols = NULL; - } else { - list_add_tail(&This->session->clients, &This->entry); - This->stream = stream; - This->channel_count = channel_count; - set_stream_volumes(This); - } - - sessions_unlock(); - - return params.result; + return stream_init(This, mode, flags, duration, period, fmt, sessionguid); }
static HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *out) @@ -1025,7 +1034,7 @@ static HRESULT WINAPI client_InitializeSharedAudioStream(IAudioClient3 *iface, D return E_POINTER;
duration = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec; - return client_Initialize(iface, AUDCLNT_SHAREMODE_SHARED, flags, duration, 0, format, session_guid); + return stream_init(This, AUDCLNT_SHAREMODE_SHARED, flags, duration, 0, format, session_guid); }
const IAudioClient3Vtbl AudioClient3_Vtbl =
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/client.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 7a141f03e19..1d6eefd5dbb 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -117,7 +117,7 @@ static HRESULT get_periods(struct audio_client *client, return params.result; }
-static HRESULT adjust_timing(struct audio_client *client, +static HRESULT adjust_timing(struct audio_client *client, const BOOLEAN force_def_period, REFERENCE_TIME *duration, REFERENCE_TIME *period, const AUDCLNT_SHAREMODE mode, const DWORD flags, const WAVEFORMATEX *fmt) @@ -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 || force_def_period) + *period = def_period; + else if (*period < min_period) + return AUDCLNT_E_INVALID_DEVICE_PERIOD; if (*duration < 3 * *period) *duration = 3 * *period; } else { @@ -355,7 +358,7 @@ skip: return wcsdup(name); }
-static HRESULT stream_init(struct audio_client *client, +static HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_period, const AUDCLNT_SHAREMODE mode, const DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period, const WAVEFORMATEX *fmt, const GUID *sessionguid) @@ -387,7 +390,7 @@ static HRESULT stream_init(struct audio_client *client, return E_INVALIDARG; }
- if (FAILED(params.result = adjust_timing(client, &duration, &period, mode, flags, fmt))) + if (FAILED(params.result = adjust_timing(client, force_def_period, &duration, &period, mode, flags, fmt))) return params.result;
sessions_lock(); @@ -636,7 +639,7 @@ static HRESULT WINAPI client_Initialize(IAudioClient3 *iface, AUDCLNT_SHAREMODE wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
- return stream_init(This, mode, flags, duration, period, fmt, sessionguid); + return stream_init(This, TRUE, mode, flags, duration, period, fmt, sessionguid); }
static HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *out) @@ -1027,14 +1030,16 @@ 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; + + 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 stream_init(This, AUDCLNT_SHAREMODE_SHARED, flags, duration, 0, format, session_guid); + period = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec; + + return stream_init(This, FALSE, AUDCLNT_SHAREMODE_SHARED, flags, 0, period, format, session_guid); }
const IAudioClient3Vtbl AudioClient3_Vtbl =
From: Davide Beatrici git@davidebeatrici.dev
--- dlls/mmdevapi/client.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 1d6eefd5dbb..e0344aefa54 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -1002,17 +1002,23 @@ 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 (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 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index e0344aefa54..132b6abae5e 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -1026,8 +1026,18 @@ 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 dummy; + 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; + + return client_GetSharedModeEnginePeriod(iface, *cur_format, cur_period_frames, &dummy, &dummy, &dummy); }
static HRESULT WINAPI client_InitializeSharedAudioStream(IAudioClient3 *iface, DWORD flags,
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146480
Your paranoid android.
=== debian11b (64 bit WoW report) ===
dinput: joystick8.c:5759: Test failed: input 1: WaitForSingleObject returned 0x102 joystick8.c:5760: Test failed: input 1: got 0 WM_INPUT messages joystick8.c:5763: Test failed: input 1: got dwType 0 joystick8.c:5764: Test failed: input 1: got header.dwSize 0 joystick8.c:5766: Test failed: input 1: got hDevice 0000000000000000 joystick8.c:5768: Test failed: input 1: got dwSizeHid 0 joystick8.c:5769: Test failed: input 1: got dwCount 0
kernel32: comm.c:1574: Test failed: AbortWaitCts hComPortEvent failed comm.c:1586: Test failed: Unexpected time 1001, expected around 500
This merge request was approved by Huw Davies.