Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/winecoreaudio.drv/coreaudio.c | 93 ++++++++++++++++++++++ dlls/winecoreaudio.drv/mmdevdrv.c | 119 ++--------------------------- dlls/winecoreaudio.drv/unixlib.h | 8 ++ 3 files changed, 109 insertions(+), 111 deletions(-)
diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index 56504a8b7b0..2d5aa29555a 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -1127,6 +1127,98 @@ static NTSTATUS get_buffer_size(void *args) return STATUS_SUCCESS; }
+static HRESULT ca_get_max_stream_latency(struct coreaudio_stream *stream, UInt32 *max) +{ + AudioObjectPropertyAddress addr; + AudioStreamID *ids; + UInt32 size; + OSStatus sc; + int nstreams, i; + + addr.mScope = get_scope(stream->flow); + addr.mElement = 0; + addr.mSelector = kAudioDevicePropertyStreams; + + sc = AudioObjectGetPropertyDataSize(stream->dev_id, &addr, 0, NULL, &size); + if(sc != noErr){ + WARN("Unable to get size for _Streams property: %x\n", (int)sc); + return osstatus_to_hresult(sc); + } + + ids = malloc(size); + if(!ids) + return E_OUTOFMEMORY; + + sc = AudioObjectGetPropertyData(stream->dev_id, &addr, 0, NULL, &size, ids); + if(sc != noErr){ + WARN("Unable to get _Streams property: %x\n", (int)sc); + free(ids); + return osstatus_to_hresult(sc); + } + + nstreams = size / sizeof(AudioStreamID); + *max = 0; + + addr.mSelector = kAudioStreamPropertyLatency; + for(i = 0; i < nstreams; ++i){ + UInt32 latency; + + size = sizeof(latency); + sc = AudioObjectGetPropertyData(ids[i], &addr, 0, NULL, &size, &latency); + if(sc != noErr){ + WARN("Unable to get _Latency property: %x\n", (int)sc); + continue; + } + + if(latency > *max) + *max = latency; + } + + free(ids); + + return S_OK; +} + +static NTSTATUS get_latency(void *args) +{ + struct get_latency_params *params = args; + struct coreaudio_stream *stream = params->stream; + UInt32 latency, stream_latency, size; + AudioObjectPropertyAddress addr; + OSStatus sc; + + OSSpinLockLock(&stream->lock); + + addr.mScope = get_scope(stream->flow); + addr.mSelector = kAudioDevicePropertyLatency; + addr.mElement = 0; + + size = sizeof(latency); + sc = AudioObjectGetPropertyData(stream->dev_id, &addr, 0, NULL, &size, &latency); + if(sc != noErr){ + WARN("Couldn't get _Latency property: %x\n", (int)sc); + OSSpinLockUnlock(&stream->lock); + params->result = osstatus_to_hresult(sc); + return STATUS_SUCCESS; + } + + params->result = ca_get_max_stream_latency(stream, &stream_latency); + if(FAILED(params->result)){ + OSSpinLockUnlock(&stream->lock); + return STATUS_SUCCESS; + } + + latency += stream_latency; + /* pretend we process audio in Period chunks, so max latency includes + * the period time */ + *params->latency = muldiv(latency, 10000000, stream->fmt->nSamplesPerSec) + + stream->period_ms * 10000; + + OSSpinLockUnlock(&stream->lock); + params->result = S_OK; + return STATUS_SUCCESS; +} + unixlib_entry_t __wine_unix_call_funcs[] = { get_endpoint_ids, @@ -1135,6 +1227,7 @@ unixlib_entry_t __wine_unix_call_funcs[] = get_mix_format, is_format_supported, get_buffer_size, + get_latency,
capture_resample /* temporary */ }; diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index cd33cababd1..63deb458f1a 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -130,7 +130,6 @@ struct ACImpl { float *vols;
AudioDeviceID adevid; - AudioObjectPropertyScope scope; HANDLE timer;
AudioSession *session; @@ -263,19 +262,6 @@ int WINAPI AUDDRV_GetPriority(void) return Priority_Neutral; }
-static HRESULT osstatus_to_hresult(OSStatus sc) -{ - switch(sc){ - case kAudioFormatUnsupportedDataFormatError: - case kAudioFormatUnknownFormatError: - case kAudioDeviceUnsupportedFormatError: - return AUDCLNT_E_UNSUPPORTED_FORMAT; - case kAudioHardwareBadDeviceError: - return AUDCLNT_E_DEVICE_INVALIDATED; - } - return E_FAIL; -} - static void set_device_guid(EDataFlow flow, HKEY drv_key, const WCHAR *key_name, GUID *guid) { @@ -481,6 +467,9 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient if(!get_deviceid_by_guid(guid, &adevid, &dataflow)) return AUDCLNT_E_DEVICE_INVALIDATED;
+ if(dataflow != eRender && dataflow != eCapture) + return E_INVALIDARG; + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl)); if(!This) return E_OUTOFMEMORY; @@ -494,15 +483,6 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
This->dataflow = dataflow;
- if(dataflow == eRender) - This->scope = kAudioDevicePropertyScopeOutput; - else if(dataflow == eCapture) - This->scope = kAudioDevicePropertyScopeInput; - else{ - HeapFree(GetProcessHeap(), 0, This); - return E_INVALIDARG; - } - hr = CoCreateFreeThreadedMarshaler((IUnknown *)&This->IAudioClient3_iface, &This->pUnkFTMarshal); if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, This); @@ -871,68 +851,11 @@ static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface, return params.result; }
-static HRESULT ca_get_max_stream_latency(ACImpl *This, UInt32 *max) -{ - AudioObjectPropertyAddress addr; - AudioStreamID *ids; - UInt32 size; - OSStatus sc; - int nstreams, i; - - addr.mScope = This->scope; - addr.mElement = 0; - addr.mSelector = kAudioDevicePropertyStreams; - - sc = AudioObjectGetPropertyDataSize(This->adevid, &addr, 0, NULL, - &size); - if(sc != noErr){ - WARN("Unable to get size for _Streams property: %x\n", (int)sc); - return osstatus_to_hresult(sc); - } - - ids = HeapAlloc(GetProcessHeap(), 0, size); - if(!ids) - return E_OUTOFMEMORY; - - sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL, &size, ids); - if(sc != noErr){ - WARN("Unable to get _Streams property: %x\n", (int)sc); - HeapFree(GetProcessHeap(), 0, ids); - return osstatus_to_hresult(sc); - } - - nstreams = size / sizeof(AudioStreamID); - *max = 0; - - addr.mSelector = kAudioStreamPropertyLatency; - for(i = 0; i < nstreams; ++i){ - UInt32 latency; - - size = sizeof(latency); - sc = AudioObjectGetPropertyData(ids[i], &addr, 0, NULL, - &size, &latency); - if(sc != noErr){ - WARN("Unable to get _Latency property: %x\n", (int)sc); - continue; - } - - if(latency > *max) - *max = latency; - } - - HeapFree(GetProcessHeap(), 0, ids); - - return S_OK; -} - static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface, REFERENCE_TIME *out) { ACImpl *This = impl_from_IAudioClient3(iface); - UInt32 latency, stream_latency, size; - AudioObjectPropertyAddress addr; - OSStatus sc; - HRESULT hr; + struct get_latency_params params;
TRACE("(%p)->(%p)\n", This, out);
@@ -942,36 +865,10 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface, if(!This->stream) return AUDCLNT_E_NOT_INITIALIZED;
- OSSpinLockLock(&This->stream->lock); - - addr.mScope = This->scope; - addr.mSelector = kAudioDevicePropertyLatency; - addr.mElement = 0; - - size = sizeof(latency); - sc = AudioObjectGetPropertyData(This->adevid, &addr, 0, NULL, - &size, &latency); - if(sc != noErr){ - WARN("Couldn't get _Latency property: %x\n", (int)sc); - OSSpinLockUnlock(&This->stream->lock); - return osstatus_to_hresult(sc); - } - - hr = ca_get_max_stream_latency(This, &stream_latency); - if(FAILED(hr)){ - OSSpinLockUnlock(&This->stream->lock); - return hr; - } - - latency += stream_latency; - /* pretend we process audio in Period chunks, so max latency includes - * the period time */ - *out = MulDiv(latency, 10000000, This->stream->fmt->nSamplesPerSec) - + This->stream->period_ms * 10000; - - OSSpinLockUnlock(&This->stream->lock); - - return S_OK; + params.stream = This->stream; + params.latency = out; + UNIX_CALL(get_latency, ¶ms); + return params.result; }
static HRESULT AudioClient_GetCurrentPadding_nolock(ACImpl *This, diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h index 7e08b347b02..dd86cd81973 100644 --- a/dlls/winecoreaudio.drv/unixlib.h +++ b/dlls/winecoreaudio.drv/unixlib.h @@ -100,6 +100,13 @@ struct get_buffer_size_params UINT32 *frames; };
+struct get_latency_params +{ + struct coreaudio_stream *stream; + HRESULT result; + REFERENCE_TIME *latency; +}; + enum unix_funcs { unix_get_endpoint_ids, @@ -108,6 +115,7 @@ enum unix_funcs unix_get_mix_format, unix_is_format_supported, unix_get_buffer_size, + unix_get_latency,
unix_capture_resample /* temporary */ };