[PATCH v2 4/6] winealsa: Move stop to the unixlib.

Huw Davies huw at codeweavers.com
Wed Mar 2 04:53:18 CST 2022


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/winealsa.drv/alsa.c     | 60 ++++++++++++++++++++++++++++++++++++
 dlls/winealsa.drv/mmdevdrv.c | 51 +++---------------------------
 dlls/winealsa.drv/unixlib.h  |  7 +++++
 3 files changed, 71 insertions(+), 47 deletions(-)

diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index a5558718f47..e5efb6b201b 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -1409,6 +1409,47 @@ exit:
         NtSetEvent(stream->event, NULL);
 }
 
+static snd_pcm_uframes_t interp_elapsed_frames(struct alsa_stream *stream)
+{
+    LARGE_INTEGER time_freq, current_time, time_diff;
+
+    NtQueryPerformanceCounter(&current_time, &time_freq);
+    time_diff.QuadPart = current_time.QuadPart - stream->last_period_time.QuadPart;
+    return muldiv(time_diff.QuadPart, stream->fmt->nSamplesPerSec, time_freq.QuadPart);
+}
+
+static int alsa_rewind_best_effort(struct alsa_stream *stream)
+{
+    snd_pcm_uframes_t len, leave;
+
+    /* we can't use snd_pcm_rewindable, some PCM devices crash. so follow
+     * PulseAudio's example and rewind as much data as we believe is in the
+     * buffer, minus 1.33ms for safety. */
+
+    /* amount of data to leave in ALSA buffer */
+    leave = interp_elapsed_frames(stream) + stream->safe_rewind_frames;
+
+    if(stream->held_frames < leave)
+        stream->held_frames = 0;
+    else
+        stream->held_frames -= leave;
+
+    if(stream->data_in_alsa_frames < leave)
+        len = 0;
+    else
+        len = stream->data_in_alsa_frames - leave;
+
+    TRACE("rewinding %lu frames, now held %u\n", len, stream->held_frames);
+
+    if(len)
+        /* snd_pcm_rewind return value is often broken, assume it succeeded */
+        snd_pcm_rewind(stream->pcm_handle, len);
+
+    stream->data_in_alsa_frames = 0;
+
+    return len;
+}
+
 static NTSTATUS start(void *args)
 {
     struct start_params *params = args;
@@ -1455,6 +1496,24 @@ static NTSTATUS start(void *args)
     return alsa_unlock_result(stream, &params->result, S_OK);
 }
 
+static NTSTATUS stop(void *args)
+{
+    struct stop_params *params = args;
+    struct alsa_stream *stream = params->stream;
+
+    alsa_lock(stream);
+
+    if(!stream->started)
+        return alsa_unlock_result(stream, &params->result, S_FALSE);
+
+    if(stream->flow == eRender)
+        alsa_rewind_best_effort(stream);
+
+    stream->started = FALSE;
+
+    return alsa_unlock_result(stream, &params->result, S_OK);
+}
+
 static NTSTATUS timer_loop(void *args)
 {
     struct timer_loop_params *params = args;
@@ -1801,6 +1860,7 @@ unixlib_entry_t __wine_unix_call_funcs[] =
     create_stream,
     release_stream,
     start,
+    stop,
     timer_loop,
     is_format_supported,
     get_mix_format,
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index 5eab548e606..d9e96b7790c 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -972,39 +972,6 @@ static snd_pcm_uframes_t interp_elapsed_frames(struct alsa_stream *stream)
     return MulDiv(time_diff.QuadPart, stream->fmt->nSamplesPerSec, time_freq.QuadPart);
 }
 
-static int alsa_rewind_best_effort(ACImpl *This)
-{
-    struct alsa_stream *stream = This->stream;
-    snd_pcm_uframes_t len, leave;
-
-    /* we can't use snd_pcm_rewindable, some PCM devices crash. so follow
-     * PulseAudio's example and rewind as much data as we believe is in the
-     * buffer, minus 1.33ms for safety. */
-
-    /* amount of data to leave in ALSA buffer */
-    leave = interp_elapsed_frames(stream) + stream->safe_rewind_frames;
-
-    if(stream->held_frames < leave)
-        stream->held_frames = 0;
-    else
-        stream->held_frames -= leave;
-
-    if(stream->data_in_alsa_frames < leave)
-        len = 0;
-    else
-        len = stream->data_in_alsa_frames - leave;
-
-    TRACE("rewinding %lu frames, now held %u\n", len, stream->held_frames);
-
-    if(len)
-        /* snd_pcm_rewind return value is often broken, assume it succeeded */
-        snd_pcm_rewind(stream->pcm_handle, len);
-
-    stream->data_in_alsa_frames = 0;
-
-    return len;
-}
-
 static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
 {
     ACImpl *This = impl_from_IAudioClient3(iface);
@@ -1036,28 +1003,18 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
 static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
 {
     ACImpl *This = impl_from_IAudioClient3(iface);
-    struct alsa_stream *stream = This->stream;
+    struct stop_params params;
 
     TRACE("(%p)\n", This);
 
     if(!This->stream)
         return AUDCLNT_E_NOT_INITIALIZED;
 
-    alsa_lock(stream);
-
-    if(!stream->started){
-        alsa_unlock(stream);
-        return S_FALSE;
-    }
-
-    if(stream->flow == eRender)
-        alsa_rewind_best_effort(This);
-
-    stream->started = FALSE;
+    params.stream = This->stream;
 
-    alsa_unlock(stream);
+    ALSA_CALL(stop, &params);
 
-    return S_OK;
+    return params.result;
 }
 
 static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index c058a920b6e..1c3caabcc26 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -97,6 +97,12 @@ struct start_params
     HRESULT result;
 };
 
+struct stop_params
+{
+    struct alsa_stream *stream;
+    HRESULT result;
+};
+
 struct timer_loop_params
 {
     struct alsa_stream *stream;
@@ -147,6 +153,7 @@ enum alsa_funcs
     alsa_create_stream,
     alsa_release_stream,
     alsa_start,
+    alsa_stop,
     alsa_timer_loop,
     alsa_is_format_supported,
     alsa_get_mix_format,
-- 
2.25.1




More information about the wine-devel mailing list