winecoreaudio: Move get_latency to the unixlib.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2021-11-23 07:55:01 +00:00 committed by Alexandre Julliard
parent 68c63beeca
commit 881e0f18fb
3 changed files with 109 additions and 111 deletions

View File

@ -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 */
};

View File

@ -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, &params);
return params.result;
}
static HRESULT AudioClient_GetCurrentPadding_nolock(ACImpl *This,

View File

@ -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 */
};