wineandroid: Check that Android supports the format in IsFormatSupported.

Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Andrew Eikum 2017-10-06 11:20:35 -05:00 committed by Alexandre Julliard
parent de9d224996
commit d2f904e07f
1 changed files with 126 additions and 73 deletions

View File

@ -683,17 +683,112 @@ static HRESULT waveformat_to_pcm(ACImpl *This, const WAVEFORMATEX *fmt, SLAndroi
return S_OK; 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, static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration, AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration,
REFERENCE_TIME period, const WAVEFORMATEX *fmt, REFERENCE_TIME period, const WAVEFORMATEX *fmt,
const GUID *sessionguid) const GUID *sessionguid)
{ {
ACImpl *This = impl_from_IAudioClient(iface); ACImpl *This = impl_from_IAudioClient(iface);
int i; int i, num_buffers;
HRESULT hr; HRESULT hr;
SLresult sr; SLresult sr;
SLAndroidDataFormat_PCM_EX pcm; SLAndroidDataFormat_PCM_EX pcm;
SLDataLocator_AndroidSimpleBufferQueue loc_bq;
TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags, TRACE("(%p)->(%x, %x, %s, %s, %p, %s)\n", This, mode, flags,
wine_dbgstr_longlong(duration), wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid)); 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; return hr;
} }
num_buffers = This->bufsize_frames / This->period_frames;
if(This->dataflow == eRender){ if(This->dataflow == eRender){
SLDataSource source; hr = try_open_render_device(&pcm, num_buffers, &This->player);
SLDataSink sink; if(FAILED(hr)){
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);
LeaveCriticalSection(&This->lock); LeaveCriticalSection(&This->lock);
return E_FAIL; return hr;
}
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;
} }
sr = SLCALL(This->player, GetInterface, *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE, &This->bufq); sr = SLCALL(This->player, GetInterface, *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE, &This->bufq);
@ -820,42 +885,10 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
return E_FAIL; return E_FAIL;
} }
}else{ }else{
SLDataSource source; hr = try_open_capture_device(&pcm, num_buffers, &This->recorder);
SLDataSink sink; if(FAILED(hr)){
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);
LeaveCriticalSection(&This->lock); LeaveCriticalSection(&This->lock);
return E_FAIL; return hr;
}
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;
} }
sr = SLCALL(This->recorder, GetInterface, *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE, &This->bufq); sr = SLCALL(This->recorder, GetInterface, *pSL_IID_ANDROIDSIMPLEBUFFERQUEUE, &This->bufq);
@ -971,7 +1004,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface,
This->initted = TRUE; 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); This->bufsize_frames, This->period_frames);
LeaveCriticalSection(&This->lock); LeaveCriticalSection(&This->lock);
@ -1083,7 +1116,27 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient *iface,
*outpwfx = NULL; *outpwfx = NULL;
hr = waveformat_to_pcm(This, pwfx, &pcm); 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); TRACE("returning: %08x\n", hr);
return hr; return hr;
} }