diff --git a/dlls/wineandroid.drv/mmdevdrv.c b/dlls/wineandroid.drv/mmdevdrv.c index 84aafb7dea5..c138fb83e59 100644 --- a/dlls/wineandroid.drv/mmdevdrv.c +++ b/dlls/wineandroid.drv/mmdevdrv.c @@ -683,17 +683,112 @@ static HRESULT waveformat_to_pcm(ACImpl *This, const WAVEFORMATEX *fmt, SLAndroi return S_OK; } +static HRESULT try_open_render_device(SLAndroidDataFormat_PCM_EX *pcm, unsigned int num_buffers, SLObjectItf *out) +{ + SLresult sr; + SLDataSource source; + SLDataSink sink; + SLDataLocator_OutputMix loc_outmix; + SLboolean required[2]; + SLInterfaceID iids[2]; + SLDataLocator_AndroidSimpleBufferQueue loc_bq; + SLObjectItf player; + + loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; + loc_bq.numBuffers = num_buffers; + source.pLocator = &loc_bq; + source.pFormat = pcm; + + loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; + loc_outmix.outputMix = outputmix; + sink.pLocator = &loc_outmix; + sink.pFormat = NULL; + + required[0] = SL_BOOLEAN_TRUE; + iids[0] = *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE; + required[1] = SL_BOOLEAN_TRUE; + iids[1] = *pSL_IID_PLAYBACKRATE; + + sr = SLCALL(engine, CreateAudioPlayer, &player, &source, &sink, + 2, iids, required); + if(sr != SL_RESULT_SUCCESS){ + WARN("CreateAudioPlayer failed: 0x%x\n", sr); + return E_FAIL; + } + + sr = SLCALL(player, Realize, SL_BOOLEAN_FALSE); + if(sr != SL_RESULT_SUCCESS){ + SLCALL_N(player, Destroy); + WARN("Player Realize failed: 0x%x\n", sr); + return E_FAIL; + } + + if(out) + *out = player; + else + SLCALL_N(player, Destroy); + + return S_OK; +} + +static HRESULT try_open_capture_device(SLAndroidDataFormat_PCM_EX *pcm, unsigned int num_buffers, SLObjectItf *out) +{ + SLresult sr; + SLDataSource source; + SLDataSink sink; + SLDataLocator_IODevice loc_mic; + SLboolean required[1]; + SLInterfaceID iids[1]; + SLDataLocator_AndroidSimpleBufferQueue loc_bq; + SLObjectItf recorder; + + loc_mic.locatorType = SL_DATALOCATOR_IODEVICE; + loc_mic.deviceType = SL_IODEVICE_AUDIOINPUT; + loc_mic.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; + loc_mic.device = NULL; + source.pLocator = &loc_mic; + source.pFormat = NULL; + + loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; + loc_bq.numBuffers = num_buffers; + sink.pLocator = &loc_bq; + sink.pFormat = pcm; + + required[0] = SL_BOOLEAN_TRUE; + iids[0] = *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE; + + sr = SLCALL(engine, CreateAudioRecorder, &recorder, &source, &sink, + 1, iids, required); + if(sr != SL_RESULT_SUCCESS){ + WARN("CreateAudioRecorder failed: 0x%x\n", sr); + return E_FAIL; + } + + sr = SLCALL(recorder, Realize, SL_BOOLEAN_FALSE); + if(sr != SL_RESULT_SUCCESS){ + SLCALL_N(recorder, Destroy); + WARN("Recorder Realize failed: 0x%x\n", sr); + return E_FAIL; + } + + if(out) + *out = recorder; + else + SLCALL_N(recorder, Destroy); + + return S_OK; +} + static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period, const WAVEFORMATEX *fmt, const GUID *sessionguid) { ACImpl *This = impl_from_IAudioClient(iface); - int i; + int i, num_buffers; HRESULT hr; SLresult sr; SLAndroidDataFormat_PCM_EX pcm; - SLDataLocator_AndroidSimpleBufferQueue loc_bq; TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags, wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid)); @@ -763,43 +858,13 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, return hr; } + num_buffers = This->bufsize_frames / This->period_frames; + if(This->dataflow == eRender){ - SLDataSource source; - SLDataSink sink; - SLDataLocator_OutputMix loc_outmix; - SLboolean required[2]; - SLInterfaceID iids[2]; - - loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - loc_bq.numBuffers = This->bufsize_frames / This->period_frames; - source.pLocator = &loc_bq; - source.pFormat = &pcm; - - loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; - loc_outmix.outputMix = outputmix; - sink.pLocator = &loc_outmix; - sink.pFormat = NULL; - - required[0] = SL_BOOLEAN_TRUE; - iids[0] = *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE; - required[1] = SL_BOOLEAN_TRUE; - iids[1] = *pSL_IID_PLAYBACKRATE; - - sr = SLCALL(engine, CreateAudioPlayer, &This->player, &source, &sink, - 2, iids, required); - if(sr != SL_RESULT_SUCCESS){ - WARN("CreateAudioPlayer failed: 0x%x\n", sr); + hr = try_open_render_device(&pcm, num_buffers, &This->player); + if(FAILED(hr)){ LeaveCriticalSection(&This->lock); - return E_FAIL; - } - - sr = SLCALL(This->player, Realize, SL_BOOLEAN_FALSE); - if(sr != SL_RESULT_SUCCESS){ - SLCALL_N(This->player, Destroy); - This->player = NULL; - WARN("Player Realize failed: 0x%x\n", sr); - LeaveCriticalSection(&This->lock); - return E_FAIL; + return hr; } sr = SLCALL(This->player, GetInterface, *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE, &This->bufq); @@ -820,42 +885,10 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, return E_FAIL; } }else{ - SLDataSource source; - SLDataSink sink; - SLDataLocator_IODevice loc_mic; - SLboolean required[1]; - SLInterfaceID iids[1]; - - loc_mic.locatorType = SL_DATALOCATOR_IODEVICE; - loc_mic.deviceType = SL_IODEVICE_AUDIOINPUT; - loc_mic.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; - loc_mic.device = NULL; - source.pLocator = &loc_mic; - source.pFormat = NULL; - - loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - loc_bq.numBuffers = This->bufsize_frames / This->period_frames; - sink.pLocator = &loc_bq; - sink.pFormat = &pcm; - - required[0] = SL_BOOLEAN_TRUE; - iids[0] = *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE; - - sr = SLCALL(engine, CreateAudioRecorder, &This->recorder, &source, &sink, - 1, iids, required); - if(sr != SL_RESULT_SUCCESS){ - WARN("CreateAudioRecorder failed: 0x%x\n", sr); + hr = try_open_capture_device(&pcm, num_buffers, &This->recorder); + if(FAILED(hr)){ LeaveCriticalSection(&This->lock); - return E_FAIL; - } - - sr = SLCALL(This->recorder, Realize, SL_BOOLEAN_FALSE); - if(sr != SL_RESULT_SUCCESS){ - SLCALL_N(This->recorder, Destroy); - This->recorder = NULL; - WARN("Recorder Realize failed: 0x%x\n", sr); - LeaveCriticalSection(&This->lock); - return E_FAIL; + return hr; } sr = SLCALL(This->recorder, GetInterface, *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE, &This->bufq); @@ -971,7 +1004,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, This->initted = TRUE; - TRACE("numBuffers: %u, bufsize: %u, period: %u\n", loc_bq.numBuffers, + TRACE("numBuffers: %u, bufsize: %u, period: %u\n", num_buffers, This->bufsize_frames, This->period_frames); LeaveCriticalSection(&This->lock); @@ -1083,7 +1116,27 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface, *outpwfx = NULL; hr = waveformat_to_pcm(This, pwfx, &pcm); + if(SUCCEEDED(hr)){ + if(This->dataflow == eRender){ + hr = try_open_render_device(&pcm, 10, NULL); + }else{ + hr = try_open_capture_device(&pcm, 10, NULL); + } + } + + if(FAILED(hr)){ + if(outpwfx){ + hr = IAudioClient_GetMixFormat(iface, outpwfx); + if(FAILED(hr)) + return hr; + return S_FALSE; + } + + hr = AUDCLNT_E_UNSUPPORTED_FORMAT; + } + TRACE("returning: %08x\n", hr); + return hr; }