From: Davide Beatrici git@davidebeatrici.dev
--- dlls/winecoreaudio.drv/coreaudio.c | 111 ++++- dlls/winecoreaudio.drv/mmdevdrv.c | 661 +---------------------------- 2 files changed, 106 insertions(+), 666 deletions(-)
diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index ecd137ce609..b3f92f04485 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -100,6 +100,9 @@ struct coreaudio_stream BYTE *local_buffer, *cap_buffer, *wrap_buffer, *resamp_buffer, *tmp_buffer; };
+static const REFERENCE_TIME g_def_period = 100000; +static const REFERENCE_TIME g_min_period = 50000; + static NTSTATUS unix_not_implemented(void *args) { return STATUS_SUCCESS; @@ -193,6 +196,13 @@ static BOOL device_has_channels(AudioDeviceID device, EDataFlow flow) return ret; }
+static NTSTATUS unix_main_loop(void *args) +{ + struct main_loop_params *params = args; + NtSetEvent(params->event, NULL); + return STATUS_SUCCESS; +} + static NTSTATUS unix_get_endpoint_ids(void *args) { struct get_endpoint_ids_params *params = args; @@ -646,12 +656,54 @@ static AudioDeviceID dev_id_from_device(const char *device) static NTSTATUS unix_create_stream(void *args) { struct create_stream_params *params = args; - struct coreaudio_stream *stream = calloc(1, sizeof(*stream)); + struct coreaudio_stream *stream; AURenderCallbackStruct input; OSStatus sc; SIZE_T size;
- if(!stream){ + if (params->share == AUDCLNT_SHAREMODE_SHARED) { + params->period = g_def_period; + if (params->duration < 3 * params->period) + params->duration = 3 * params->period; + } else { + WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE *)params->fmt; + if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) { + if (fmtex->dwChannelMask == 0 || fmtex->dwChannelMask & SPEAKER_RESERVED) { + params->result = AUDCLNT_E_UNSUPPORTED_FORMAT; + return STATUS_SUCCESS; + } + } + + if (!params->period) + params->period = g_def_period; /* not minimum */ + + if (params->period < g_min_period || params->period > 5000000) { + params->result = AUDCLNT_E_INVALID_DEVICE_PERIOD; + return STATUS_SUCCESS; + } + + if (params->duration > 20000000) { /* the smaller the period, the lower this limit */ + params->result = AUDCLNT_E_BUFFER_SIZE_ERROR; + return STATUS_SUCCESS; + } + + if (params->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) { + if (params->duration != params->period) { + params->result = AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL; + return STATUS_SUCCESS; + } + + FIXME("EXCLUSIVE mode with EVENTCALLBACK\n"); + + params->result = AUDCLNT_E_DEVICE_IN_USE; + return STATUS_SUCCESS; + } else { + if (params->duration < 8 * params->period) + params->duration = 8 * params->period; /* may grow above 2s */ + } + } + + if (!(stream = calloc(1, sizeof(*stream)))) { params->result = E_OUTOFMEMORY; return STATUS_SUCCESS; } @@ -1087,6 +1139,18 @@ unsupported: return STATUS_SUCCESS; }
+static NTSTATUS unix_get_device_period(void *args) +{ + struct get_device_period_params *params = args; + + if (params->def_period) + *params->def_period = g_def_period; + if (params->min_period) + *params->min_period = g_min_period; + + return STATUS_SUCCESS; +} + static UINT buf_ptr_diff(UINT left, UINT right, UINT bufsize) { if(left <= right) @@ -1725,7 +1789,7 @@ unixlib_entry_t __wine_unix_call_funcs[] = { unix_not_implemented, unix_not_implemented, - unix_not_implemented, + unix_main_loop, unix_get_endpoint_ids, unix_create_stream, unix_release_stream, @@ -1739,7 +1803,7 @@ unixlib_entry_t __wine_unix_call_funcs[] = unix_release_capture_buffer, unix_is_format_supported, unix_get_mix_format, - unix_not_implemented, + unix_get_device_period, unix_get_buffer_size, unix_get_latency, unix_get_current_padding, @@ -1763,6 +1827,19 @@ unixlib_entry_t __wine_unix_call_funcs[] =
typedef UINT PTR32;
+static NTSTATUS unix_wow64_main_loop(void *args) +{ + struct + { + PTR32 event; + } *params32 = args; + struct main_loop_params params = + { + .event = ULongToHandle(params32->event) + }; + return unix_main_loop(¶ms); +} + static NTSTATUS unix_wow64_get_endpoint_ids(void *args) { struct @@ -1934,6 +2011,28 @@ static NTSTATUS unix_wow64_get_mix_format(void *args) return STATUS_SUCCESS; }
+static NTSTATUS unix_wow64_get_device_period(void *args) +{ + struct + { + PTR32 device; + EDataFlow flow; + HRESULT result; + PTR32 def_period; + PTR32 min_period; + } *params32 = args; + struct get_device_period_params params = + { + .device = ULongToPtr(params32->device), + .flow = params32->flow, + .def_period = ULongToPtr(params32->def_period), + .min_period = ULongToPtr(params32->min_period), + }; + unix_get_device_period(¶ms); + params32->result = params.result; + return STATUS_SUCCESS; +} + static NTSTATUS unix_wow64_get_buffer_size(void *args) { struct @@ -2085,7 +2184,7 @@ unixlib_entry_t __wine_unix_call_wow64_funcs[] = { unix_not_implemented, unix_not_implemented, - unix_not_implemented, + unix_wow64_main_loop, unix_wow64_get_endpoint_ids, unix_wow64_create_stream, unix_wow64_release_stream, @@ -2099,7 +2198,7 @@ unixlib_entry_t __wine_unix_call_wow64_funcs[] = unix_release_capture_buffer, unix_wow64_is_format_supported, unix_wow64_get_mix_format, - unix_not_implemented, + unix_wow64_get_device_period, unix_wow64_get_buffer_size, unix_wow64_get_latency, unix_wow64_get_current_padding, diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index 58d001080e3..45b6b53ba29 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -46,12 +46,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(coreaudio);
-#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; - -static const IAudioClient3Vtbl AudioClient3_Vtbl; +extern const IAudioClient3Vtbl AudioClient3_Vtbl; extern const IAudioRenderClientVtbl AudioRenderClient_Vtbl; extern const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl; extern const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl; @@ -73,8 +68,6 @@ static CRITICAL_SECTION_DEBUG g_sessions_lock_debug = static CRITICAL_SECTION g_sessions_lock = { &g_sessions_lock_debug, -1, 0, 0, 0, 0 }; static struct list g_sessions = LIST_INIT(g_sessions);
-static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client); - void DECLSPEC_HIDDEN sessions_lock(void) { EnterCriticalSection(&g_sessions_lock); @@ -85,11 +78,6 @@ void DECLSPEC_HIDDEN sessions_unlock(void) LeaveCriticalSection(&g_sessions_lock); }
-static inline ACImpl *impl_from_IAudioClient3(IAudioClient3 *iface) -{ - return CONTAINING_RECORD(iface, ACImpl, IAudioClient3_iface); -} - BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved) { switch (reason) @@ -194,18 +182,6 @@ static void get_device_guid(EDataFlow flow, const char *dev, GUID *guid) RegCloseKey(key); }
-static void set_stream_volumes(ACImpl *This) -{ - struct set_volumes_params params; - - params.stream = This->stream; - params.master_volume = This->session->mute ? 0.0f : This->session->master_vol; - params.volumes = This->vols; - params.session_volumes = This->session->channel_vols; - - UNIX_CALL(set_volumes, ¶ms); -} - HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids_out, GUID **guids_out, UINT *num, UINT *def_index) { @@ -373,100 +349,6 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient return S_OK; }
-static HRESULT WINAPI AudioClient_QueryInterface(IAudioClient3 *iface, - REFIID riid, void **ppv) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IAudioClient) || - IsEqualIID(riid, &IID_IAudioClient2) || - IsEqualIID(riid, &IID_IAudioClient3)) - *ppv = iface; - else if(IsEqualIID(riid, &IID_IMarshal)) - return IUnknown_QueryInterface(This->marshal, riid, ppv); - - if(*ppv){ - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; - } - WARN("Unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI AudioClient_AddRef(IAudioClient3 *iface) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - ULONG ref; - ref = InterlockedIncrement(&This->ref); - TRACE("(%p) Refcount now %lu\n", This, ref); - return ref; -} - -static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - ULONG ref; - ref = InterlockedDecrement(&This->ref); - TRACE("(%p) Refcount now %lu\n", This, ref); - if(!ref){ - if(This->stream){ - struct release_stream_params params; - params.stream = This->stream; - params.timer_thread = This->timer_thread; - UNIX_CALL(release_stream, ¶ms); - This->stream = 0; - - sessions_lock(); - list_remove(&This->entry); - sessions_unlock(); - } - HeapFree(GetProcessHeap(), 0, This->vols); - IMMDevice_Release(This->parent); - IUnknown_Release(This->marshal); - HeapFree(GetProcessHeap(), 0, This); - } - return ref; -} - -static void dump_fmt(const WAVEFORMATEX *fmt) -{ - TRACE("wFormatTag: 0x%x (", fmt->wFormatTag); - switch(fmt->wFormatTag){ - case WAVE_FORMAT_PCM: - TRACE("WAVE_FORMAT_PCM"); - break; - case WAVE_FORMAT_IEEE_FLOAT: - TRACE("WAVE_FORMAT_IEEE_FLOAT"); - break; - case WAVE_FORMAT_EXTENSIBLE: - TRACE("WAVE_FORMAT_EXTENSIBLE"); - break; - default: - TRACE("Unknown"); - break; - } - TRACE(")\n"); - - TRACE("nChannels: %u\n", fmt->nChannels); - TRACE("nSamplesPerSec: %lu\n", fmt->nSamplesPerSec); - TRACE("nAvgBytesPerSec: %lu\n", fmt->nAvgBytesPerSec); - TRACE("nBlockAlign: %u\n", fmt->nBlockAlign); - TRACE("wBitsPerSample: %u\n", fmt->wBitsPerSample); - TRACE("cbSize: %u\n", fmt->cbSize); - - if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){ - WAVEFORMATEXTENSIBLE *fmtex = (void*)fmt; - TRACE("dwChannelMask: %08lx\n", fmtex->dwChannelMask); - TRACE("Samples: %04x\n", fmtex->Samples.wReserved); - TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex->SubFormat)); - } -} - static void session_init_vols(AudioSession *session, UINT channels) { if(session->channel_count < channels){ @@ -546,547 +428,6 @@ HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, return S_OK; }
-static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, - AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration, - REFERENCE_TIME period, const WAVEFORMATEX *fmt, - const GUID *sessionguid) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct release_stream_params release_params; - struct create_stream_params params; - stream_handle stream; - UINT32 i; - - 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(mode == AUDCLNT_SHAREMODE_SHARED){ - period = DefaultPeriod; - if( duration < 3 * period) - duration = 3 * period; - }else{ - if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){ - if(((WAVEFORMATEXTENSIBLE*)fmt)->dwChannelMask == 0 || - ((WAVEFORMATEXTENSIBLE*)fmt)->dwChannelMask & SPEAKER_RESERVED) - return AUDCLNT_E_UNSUPPORTED_FORMAT; - } - - 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; - params.share = mode; - params.flags = flags; - params.duration = duration; - params.period = period; - params.fmt = fmt; - params.channel_count = NULL; - params.stream = &stream; - - UNIX_CALL(create_stream, ¶ms); - if(FAILED(params.result)){ - sessions_unlock(); - return params.result; - } - - This->channel_count = fmt->nChannels; - - This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float)); - if(!This->vols){ - params.result = E_OUTOFMEMORY; - goto end; - } - - for(i = 0; i < This->channel_count; ++i) - This->vols[i] = 1.f; - - params.result = get_audio_session(sessionguid, This->parent, fmt->nChannels, &This->session); - if(FAILED(params.result)) goto end; - - list_add_tail(&This->session->clients, &This->entry); - -end: - if(FAILED(params.result)){ - release_params.stream = stream; - UNIX_CALL(release_stream, &release_params); - HeapFree(GetProcessHeap(), 0, This->vols); - This->vols = NULL; - }else{ - This->stream = stream; - set_stream_volumes(This); - } - - sessions_unlock(); - - return params.result; -} - -static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface, - UINT32 *frames) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct get_buffer_size_params params; - - TRACE("(%p)->(%p)\n", This, frames); - - if(!frames) - return E_POINTER; - - if(!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - - params.stream = This->stream; - params.frames = frames; - UNIX_CALL(get_buffer_size, ¶ms); - return params.result; -} - -static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface, - REFERENCE_TIME *out) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct get_latency_params params; - - TRACE("(%p)->(%p)\n", This, out); - - if(!out) - return E_POINTER; - - if(!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - - params.stream = This->stream; - params.latency = out; - UNIX_CALL(get_latency, ¶ms); - return params.result; -} - -static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient3 *iface, - UINT32 *numpad) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct get_current_padding_params params; - - TRACE("(%p)->(%p)\n", This, numpad); - - if(!numpad) - return E_POINTER; - - if(!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - - params.stream = This->stream; - params.padding = numpad; - UNIX_CALL(get_current_padding, ¶ms); - return params.result; -} - -static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface, - AUDCLNT_SHAREMODE mode, const WAVEFORMATEX *pwfx, - WAVEFORMATEX **outpwfx) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct is_format_supported_params params; - - TRACE("(%p)->(%x, %p, %p)\n", This, mode, pwfx, outpwfx); - if(pwfx) dump_fmt(pwfx); - - params.device = This->device_name; - params.flow = This->dataflow; - params.share = mode; - params.fmt_in = pwfx; - params.fmt_out = NULL; - - if(outpwfx){ - *outpwfx = NULL; - if(mode == AUDCLNT_SHAREMODE_SHARED) - params.fmt_out = CoTaskMemAlloc(sizeof(*params.fmt_out)); - } - UNIX_CALL(is_format_supported, ¶ms); - - if(params.result == S_FALSE) - *outpwfx = ¶ms.fmt_out->Format; - else - CoTaskMemFree(params.fmt_out); - - return params.result; -} - -static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface, - WAVEFORMATEX **pwfx) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct get_mix_format_params params; - - TRACE("(%p)->(%p)\n", This, pwfx); - - if(!pwfx) - return E_POINTER; - *pwfx = NULL; - - params.device = This->device_name; - params.flow = This->dataflow; - params.fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE)); - if(!params.fmt) - return E_OUTOFMEMORY; - - UNIX_CALL(get_mix_format, ¶ms); - - if(SUCCEEDED(params.result)){ - *pwfx = ¶ms.fmt->Format; - dump_fmt(*pwfx); - }else - CoTaskMemFree(params.fmt); - - return params.result; -} - -static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface, - REFERENCE_TIME *defperiod, REFERENCE_TIME *minperiod) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - - TRACE("(%p)->(%p, %p)\n", This, defperiod, minperiod); - - if(!defperiod && !minperiod) - return E_POINTER; - - if(defperiod) - *defperiod = DefaultPeriod; - if(minperiod) - *minperiod = MinimumPeriod; - - return S_OK; -} - -static DWORD WINAPI ca_timer_thread(void *user) -{ - struct timer_loop_params params; - ACImpl *This = user; - params.stream = This->stream; - SetThreadDescription(GetCurrentThread(), L"winecoreaudio_timer_loop"); - UNIX_CALL(timer_loop, ¶ms); - return 0; -} - -static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct start_params params; - HRESULT hr; - - TRACE("(%p)\n", This); - - if(!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - - params.stream = This->stream; - UNIX_CALL(start, ¶ms); - if(FAILED(hr = params.result)) - return hr; - - if(!This->timer_thread) { - This->timer_thread = CreateThread(NULL, 0, ca_timer_thread, This, 0, NULL); - SetThreadPriority(This->timer_thread, THREAD_PRIORITY_TIME_CRITICAL); - } - - return S_OK; -} - -static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct stop_params params; - - TRACE("(%p)\n", This); - - if(!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - - params.stream = This->stream; - UNIX_CALL(stop, ¶ms); - return params.result; -} - -static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct reset_params params; - - TRACE("(%p)\n", This); - - if(!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - - params.stream = This->stream; - UNIX_CALL(reset, ¶ms); - return params.result; -} - -static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface, - HANDLE event) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - struct set_event_handle_params params; - - TRACE("(%p)->(%p)\n", This, event); - - if(!event) - return E_INVALIDARG; - - if(!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - - params.stream = This->stream; - params.event = event; - UNIX_CALL(set_event_handle, ¶ms); - return params.result; -} - -static HRESULT WINAPI AudioClient_GetService(IAudioClient3 *iface, REFIID riid, - void **ppv) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - HRESULT hr; - - TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); - - if(!ppv) - return E_POINTER; - *ppv = NULL; - - if(!This->stream) - return AUDCLNT_E_NOT_INITIALIZED; - - sessions_lock(); - - if(IsEqualIID(riid, &IID_IAudioRenderClient)){ - if(This->dataflow != eRender){ - hr = AUDCLNT_E_WRONG_ENDPOINT_TYPE; - goto end; - } - IAudioRenderClient_AddRef(&This->IAudioRenderClient_iface); - *ppv = &This->IAudioRenderClient_iface; - }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){ - if(This->dataflow != eCapture){ - hr = AUDCLNT_E_WRONG_ENDPOINT_TYPE; - goto end; - } - IAudioCaptureClient_AddRef(&This->IAudioCaptureClient_iface); - *ppv = &This->IAudioCaptureClient_iface; - }else if(IsEqualIID(riid, &IID_IAudioClock)){ - IAudioClock_AddRef(&This->IAudioClock_iface); - *ppv = &This->IAudioClock_iface; - }else if(IsEqualIID(riid, &IID_IAudioStreamVolume)){ - IAudioStreamVolume_AddRef(&This->IAudioStreamVolume_iface); - *ppv = &This->IAudioStreamVolume_iface; - }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){ - if(!This->session_wrapper){ - This->session_wrapper = AudioSessionWrapper_Create(This); - if(!This->session_wrapper){ - hr = E_OUTOFMEMORY; - goto end; - } - }else - IAudioSessionControl2_AddRef(&This->session_wrapper->IAudioSessionControl2_iface); - - *ppv = &This->session_wrapper->IAudioSessionControl2_iface; - }else if(IsEqualIID(riid, &IID_IChannelAudioVolume)){ - if(!This->session_wrapper){ - This->session_wrapper = AudioSessionWrapper_Create(This); - if(!This->session_wrapper){ - hr = E_OUTOFMEMORY; - goto end; - } - }else - IChannelAudioVolume_AddRef(&This->session_wrapper->IChannelAudioVolume_iface); - - *ppv = &This->session_wrapper->IChannelAudioVolume_iface; - }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){ - if(!This->session_wrapper){ - This->session_wrapper = AudioSessionWrapper_Create(This); - if(!This->session_wrapper){ - hr = E_OUTOFMEMORY; - goto end; - } - }else - ISimpleAudioVolume_AddRef(&This->session_wrapper->ISimpleAudioVolume_iface); - - *ppv = &This->session_wrapper->ISimpleAudioVolume_iface; - } - - if(*ppv) hr = S_OK; - else{ - FIXME("stub %s\n", debugstr_guid(riid)); - hr = E_NOINTERFACE; - } - -end: - sessions_unlock(); - return hr; -} - -static HRESULT WINAPI AudioClient_IsOffloadCapable(IAudioClient3 *iface, - AUDIO_STREAM_CATEGORY category, BOOL *offload_capable) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - - TRACE("(%p)->(0x%x, %p)\n", This, category, offload_capable); - - if(!offload_capable) - return E_INVALIDARG; - - *offload_capable = FALSE; - - return S_OK; -} - -static HRESULT WINAPI AudioClient_SetClientProperties(IAudioClient3 *iface, - const AudioClientProperties *prop) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - const Win8AudioClientProperties *legacy_prop = (const Win8AudioClientProperties *)prop; - - TRACE("(%p)->(%p)\n", This, prop); - - if(!legacy_prop) - return E_POINTER; - - if(legacy_prop->cbSize == sizeof(AudioClientProperties)){ - TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n", - legacy_prop->bIsOffload, - legacy_prop->eCategory, - prop->Options); - }else if(legacy_prop->cbSize == sizeof(Win8AudioClientProperties)){ - TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n", - legacy_prop->bIsOffload, - legacy_prop->eCategory); - }else{ - WARN("Unsupported Size = %d\n", legacy_prop->cbSize); - return E_INVALIDARG; - } - - - if(legacy_prop->bIsOffload) - return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE; - - return S_OK; -} - -static HRESULT WINAPI AudioClient_GetBufferSizeLimits(IAudioClient3 *iface, - const WAVEFORMATEX *format, BOOL event_driven, REFERENCE_TIME *min_duration, - REFERENCE_TIME *max_duration) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - - FIXME("(%p)->(%p, %u, %p, %p)\n", This, format, event_driven, min_duration, max_duration); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioClient_GetSharedModeEnginePeriod(IAudioClient3 *iface, - const WAVEFORMATEX *format, UINT32 *default_period_frames, UINT32 *unit_period_frames, - UINT32 *min_period_frames, UINT32 *max_period_frames) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - - FIXME("(%p)->(%p, %p, %p, %p, %p)\n", This, format, default_period_frames, unit_period_frames, - min_period_frames, max_period_frames); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioClient_GetCurrentSharedModeEnginePeriod(IAudioClient3 *iface, - WAVEFORMATEX **cur_format, UINT32 *cur_period_frames) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - - FIXME("(%p)->(%p, %p)\n", This, cur_format, cur_period_frames); - - return E_NOTIMPL; -} - -static HRESULT WINAPI AudioClient_InitializeSharedAudioStream(IAudioClient3 *iface, - DWORD flags, UINT32 period_frames, const WAVEFORMATEX *format, - const GUID *session_guid) -{ - ACImpl *This = impl_from_IAudioClient3(iface); - - FIXME("(%p)->(0x%lx, %u, %p, %s)\n", This, flags, period_frames, format, debugstr_guid(session_guid)); - - return E_NOTIMPL; -} - -static const IAudioClient3Vtbl AudioClient3_Vtbl = -{ - AudioClient_QueryInterface, - AudioClient_AddRef, - AudioClient_Release, - AudioClient_Initialize, - AudioClient_GetBufferSize, - AudioClient_GetStreamLatency, - AudioClient_GetCurrentPadding, - AudioClient_IsFormatSupported, - AudioClient_GetMixFormat, - AudioClient_GetDevicePeriod, - AudioClient_Start, - AudioClient_Stop, - AudioClient_Reset, - AudioClient_SetEventHandle, - AudioClient_GetService, - AudioClient_IsOffloadCapable, - AudioClient_SetClientProperties, - AudioClient_GetBufferSizeLimits, - AudioClient_GetSharedModeEnginePeriod, - AudioClient_GetCurrentSharedModeEnginePeriod, - AudioClient_InitializeSharedAudioStream, -}; - static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client) { AudioSessionWrapper *ret;