Module: wine Branch: master Commit: 3ddb038513f2779ba647dac3bce48296875412aa URL: https://source.winehq.org/git/wine.git/?a=commit;h=3ddb038513f2779ba647dac3b...
Author: Huw Davies huw@codeweavers.com Date: Thu Mar 10 08:20:04 2022 +0000
winealsa: Move get_position 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
---
dlls/winealsa.drv/alsa.c | 53 +++++++++++++++++++++++++++++++++++++ dlls/winealsa.drv/mmdevdrv.c | 62 +++++--------------------------------------- dlls/winealsa.drv/unixlib.h | 9 +++++++ 3 files changed, 68 insertions(+), 56 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index 5f13ce07de6..870ec4db151 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -2110,6 +2110,58 @@ static NTSTATUS get_frequency(void *args) return alsa_unlock_result(stream, ¶ms->result, S_OK); }
+static NTSTATUS get_position(void *args) +{ + struct get_position_params *params = args; + struct alsa_stream *stream = params->stream; + UINT64 position; + snd_pcm_state_t alsa_state; + + alsa_lock(stream); + + /* avail_update required to get accurate snd_pcm_state() */ + snd_pcm_avail_update(stream->pcm_handle); + alsa_state = snd_pcm_state(stream->pcm_handle); + + if(stream->flow == eRender){ + position = stream->written_frames - stream->held_frames; + + if(stream->started && alsa_state == SND_PCM_STATE_RUNNING && stream->held_frames) + /* we should be using snd_pcm_delay here, but it is broken + * especially during ALSA device underrun. instead, let's just + * interpolate between periods with the system timer. */ + position += interp_elapsed_frames(stream); + + position = min(position, stream->written_frames - stream->held_frames + stream->mmdev_period_frames); + + position = min(position, stream->written_frames); + }else + position = stream->written_frames + stream->held_frames; + + /* ensure monotic growth */ + if(position < stream->last_pos_frames) + position = stream->last_pos_frames; + else + stream->last_pos_frames = position; + + TRACE("frames written: %u, held: %u, state: 0x%x, position: %u\n", + (UINT32)(stream->written_frames%1000000000), stream->held_frames, + alsa_state, (UINT32)(position%1000000000)); + + if(stream->share == AUDCLNT_SHAREMODE_SHARED) + *params->pos = position * stream->fmt->nBlockAlign; + else + *params->pos = position; + + if(params->qpctime){ + LARGE_INTEGER stamp, freq; + NtQueryPerformanceCounter(&stamp, &freq); + *params->qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart; + } + + return alsa_unlock_result(stream, ¶ms->result, S_OK); +} + static NTSTATUS set_event_handle(void *args) { struct set_event_handle_params *params = args; @@ -2150,5 +2202,6 @@ unixlib_entry_t __wine_unix_call_funcs[] = get_current_padding, get_next_packet_size, get_frequency, + get_position, set_event_handle, }; diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index fde97eb4cb7..6dfa3ad013f 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -951,15 +951,6 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface, return S_OK; }
-static snd_pcm_uframes_t interp_elapsed_frames(struct alsa_stream *stream) -{ - LARGE_INTEGER time_freq, current_time, time_diff; - QueryPerformanceFrequency(&time_freq); - QueryPerformanceCounter(¤t_time); - time_diff.QuadPart = current_time.QuadPart - stream->last_period_time.QuadPart; - return MulDiv(time_diff.QuadPart, stream->fmt->nSamplesPerSec, time_freq.QuadPart); -} - static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface) { ACImpl *This = impl_from_IAudioClient3(iface); @@ -1494,61 +1485,20 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos, UINT64 *qpctime) { ACImpl *This = impl_from_IAudioClock(iface); - struct alsa_stream *stream = This->stream; - UINT64 position; - snd_pcm_state_t alsa_state; + struct get_position_params params;
TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
if(!pos) return E_POINTER;
- alsa_lock(stream); - - /* avail_update required to get accurate snd_pcm_state() */ - snd_pcm_avail_update(stream->pcm_handle); - alsa_state = snd_pcm_state(stream->pcm_handle); - - if(stream->flow == eRender){ - position = stream->written_frames - stream->held_frames; - - if(stream->started && alsa_state == SND_PCM_STATE_RUNNING && stream->held_frames) - /* we should be using snd_pcm_delay here, but it is broken - * especially during ALSA device underrun. instead, let's just - * interpolate between periods with the system timer. */ - position += interp_elapsed_frames(stream); - - position = min(position, stream->written_frames - stream->held_frames + stream->mmdev_period_frames); - - position = min(position, stream->written_frames); - }else - position = stream->written_frames + stream->held_frames; - - /* ensure monotic growth */ - if(position < stream->last_pos_frames) - position = stream->last_pos_frames; - else - stream->last_pos_frames = position; - - TRACE("frames written: %u, held: %u, state: 0x%x, position: %u\n", - (UINT32)(stream->written_frames%1000000000), stream->held_frames, - alsa_state, (UINT32)(position%1000000000)); - - alsa_unlock(stream); - - if(stream->share == AUDCLNT_SHAREMODE_SHARED) - *pos = position * stream->fmt->nBlockAlign; - else - *pos = position; + params.stream = This->stream; + params.pos = pos; + params.qpctime = qpctime;
- if(qpctime){ - LARGE_INTEGER stamp, freq; - QueryPerformanceCounter(&stamp); - QueryPerformanceFrequency(&freq); - *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart; - } + ALSA_CALL(get_position, ¶ms);
- return S_OK; + return params.result; }
static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface, diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h index 6053fe9dc8a..89b53fbcb9a 100644 --- a/dlls/winealsa.drv/unixlib.h +++ b/dlls/winealsa.drv/unixlib.h @@ -201,6 +201,14 @@ struct get_frequency_params UINT64 *freq; };
+struct get_position_params +{ + struct alsa_stream *stream; + HRESULT result; + UINT64 *pos; + UINT64 *qpctime; +}; + struct set_event_handle_params { struct alsa_stream *stream; @@ -228,6 +236,7 @@ enum alsa_funcs alsa_get_current_padding, alsa_get_next_packet_size, alsa_get_frequency, + alsa_get_position, alsa_set_event_handle, };