From: Davide Beatrici git@davidebeatrici.dev
--- dlls/wineoss.drv/mmdevdrv.c | 38 ++++--------------------------------- dlls/wineoss.drv/oss.c | 35 +++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 35 deletions(-)
diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index c55176307f0..18e63756616 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -50,9 +50,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(oss);
#define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
-static const REFERENCE_TIME DefaultPeriod = 100000; -static const REFERENCE_TIME MinimumPeriod = 50000; - typedef struct _OSSDevice { struct list entry; EDataFlow flow; @@ -553,7 +550,6 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, { ACImpl *This = impl_from_IAudioClient3(iface); struct create_stream_params params; - stream_handle stream; unsigned int i;
TRACE("(%p)->(%x, %lx, %s, %s, %p, %s)\n", This, mode, flags, @@ -581,35 +577,8 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, return E_INVALIDARG; }
- if(mode == AUDCLNT_SHAREMODE_SHARED){ - period = DefaultPeriod; - if( duration < 3 * period) - duration = 3 * period; - }else{ - if(!period) - period = DefaultPeriod; /* not minimum */ - if(period < MinimumPeriod || period > 5000000) - return AUDCLNT_E_INVALID_DEVICE_PERIOD; - if(duration > 20000000) /* the smaller the period, the lower this limit */ - return AUDCLNT_E_BUFFER_SIZE_ERROR; - if(flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK){ - if(duration != period) - return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL; - FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); - return AUDCLNT_E_DEVICE_IN_USE; - }else{ - if( duration < 8 * period) - duration = 8 * period; /* may grow above 2s */ - } - } - sessions_lock();
- if(This->stream){ - sessions_unlock(); - return AUDCLNT_E_ALREADY_INITIALIZED; - } - params.name = NULL; params.device = This->device_name; params.flow = This->dataflow; @@ -619,7 +588,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, params.period = period; params.fmt = fmt; params.channel_count = NULL; - params.stream = &stream; + params.stream = &This->stream;
OSS_CALL(create_stream, ¶ms); if(FAILED(params.result)){ @@ -641,12 +610,13 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
exit: if(FAILED(params.result)){ - stream_release(stream, NULL); + stream_release(This->stream, NULL); + This->stream = 0; + HeapFree(GetProcessHeap(), 0, This->vols); This->vols = NULL; } else { list_add_tail(&This->session->clients, &This->entry); - This->stream = stream; set_stream_volumes(This); }
diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c index 585df97bc43..e837bc1f0c1 100644 --- a/dlls/wineoss.drv/oss.c +++ b/dlls/wineoss.drv/oss.c @@ -555,11 +555,44 @@ static ULONG_PTR zero_bits(void) static NTSTATUS oss_create_stream(void *args) { struct create_stream_params *params = args; - WAVEFORMATEXTENSIBLE *fmtex; + WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE *)params->fmt; struct oss_stream *stream; oss_audioinfo ai; SIZE_T size;
+ /* We don't return early as priority is given to the other errors. */ + params->result = *params->stream ? AUDCLNT_E_ALREADY_INITIALIZED : S_OK; + + if (params->share == AUDCLNT_SHAREMODE_SHARED) { + params->period = def_period; + if (params->duration < 3 * params->period) + params->duration = 3 * params->period; + } else { + if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && + (fmtex->dwChannelMask == 0 || fmtex->dwChannelMask & SPEAKER_RESERVED)) + params->result = AUDCLNT_E_UNSUPPORTED_FORMAT; + else { + if (!params->period) + params->period = def_period; + if (params->period < min_period || params->period > 5000000) + params->result = AUDCLNT_E_INVALID_DEVICE_PERIOD; + else if (params->duration > 20000000) /* The smaller the period, the lower this limit. */ + params->result = AUDCLNT_E_BUFFER_SIZE_ERROR; + else if (params->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) { + if (params->duration != params->period) + params->result = AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL; + + FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); + + params->result = AUDCLNT_E_DEVICE_IN_USE; + } else if (params->duration < 8 * params->period) + params->duration = 8 * params->period; /* May grow above 2s. */ + } + } + + if (FAILED(params->result)) + return STATUS_SUCCESS; + stream = calloc(1, sizeof(*stream)); if(!stream){ params->result = E_OUTOFMEMORY;