Signed-off-by: Huw Davies <huw(a)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 */
};
--
2.23.0