[PATCH 3/5] winealsa: Move get_position to the unixlib.
Huw Davies
huw at codeweavers.com
Thu Mar 10 02:20:04 CST 2022
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
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,
};
--
2.25.1
More information about the wine-devel
mailing list