From: Alexandre Julliard <julliard@winehq.org> --- dlls/mmdevapi/client.c | 33 +------ dlls/mmdevapi/mmdevapi_private.h | 2 - dlls/mmdevapi/unixlib.h | 7 -- dlls/winealsa.drv/alsa.c | 86 +++++++++--------- dlls/winecoreaudio.drv/coreaudio.c | 68 +++++++------- dlls/wineoss.drv/oss.c | 138 ++++++++++++++--------------- dlls/winepulse.drv/pulse.c | 20 ++--- 7 files changed, 152 insertions(+), 202 deletions(-) diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 25ba520de48..d4d3e82b466 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -192,27 +192,11 @@ static void dump_fmt(const WAVEFORMATEX *fmt) } } -static DWORD CALLBACK timer_loop_func(void *user) -{ - struct timer_loop_params params; - struct audio_client *This = user; - - SetThreadDescription(GetCurrentThread(), L"audio_client_timer"); - - params.stream = This->stream; - - wine_unix_call(timer_loop, ¶ms); - - return 0; -} - -HRESULT stream_release(stream_handle stream, HANDLE timer_thread) +static HRESULT stream_release(stream_handle stream) { struct release_stream_params params; - params.stream = stream; - params.timer_thread = timer_thread; - + params.stream = stream; wine_unix_call(release_stream, ¶ms); return params.result; @@ -533,7 +517,7 @@ static HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_ exit: if (FAILED(params.result)) { - stream_release(stream, NULL); + stream_release(stream); free(client->vols); client->vols = NULL; } else { @@ -721,7 +705,7 @@ static ULONG WINAPI client_Release(IAudioClient3 *iface) free(This->vols); if (This->stream) - stream_release(This->stream, This->timer_thread); + stream_release(This->stream); free(This->device_name); free(This); @@ -935,15 +919,6 @@ static HRESULT WINAPI client_Start(IAudioClient3 *iface) params.stream = This->stream; wine_unix_call(start, ¶ms); - if (SUCCEEDED(params.result) && !This->timer_thread) { - if ((This->timer_thread = CreateThread(NULL, 0, timer_loop_func, This, 0, NULL))) - SetThreadPriority(This->timer_thread, THREAD_PRIORITY_TIME_CRITICAL); - else { - IAudioClient3_Stop(&This->IAudioClient3_iface); - params.result = E_FAIL; - } - } - sessions_unlock(); return params.result; diff --git a/dlls/mmdevapi/mmdevapi_private.h b/dlls/mmdevapi/mmdevapi_private.h index 6a04e9077ef..b475d819558 100644 --- a/dlls/mmdevapi/mmdevapi_private.h +++ b/dlls/mmdevapi/mmdevapi_private.h @@ -75,8 +75,6 @@ struct audio_client { UINT32 channel_count; stream_handle stream; - HANDLE timer_thread; - struct audio_session *session; struct audio_session_wrapper *session_wrapper; diff --git a/dlls/mmdevapi/unixlib.h b/dlls/mmdevapi/unixlib.h index c46a4ff4e98..ddb6bd1005a 100644 --- a/dlls/mmdevapi/unixlib.h +++ b/dlls/mmdevapi/unixlib.h @@ -83,7 +83,6 @@ struct create_stream_params struct release_stream_params { stream_handle stream; - HANDLE timer_thread; HRESULT result; }; @@ -105,11 +104,6 @@ struct reset_params HRESULT result; }; -struct timer_loop_params -{ - stream_handle stream; -}; - struct get_render_buffer_params { stream_handle stream; @@ -337,7 +331,6 @@ enum unix_funcs start, stop, reset, - timer_loop, get_render_buffer, release_render_buffer, get_capture_buffer, diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index 9497c06059c..1f1badd3e90 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -58,6 +58,7 @@ struct alsa_stream AUDCLNT_SHAREMODE share; EDataFlow flow; HANDLE event; + HANDLE timer_thread; BOOL need_remapping; int alsa_channels; @@ -1024,10 +1025,10 @@ static NTSTATUS alsa_release_stream(void *args) struct alsa_stream *stream = handle_get_stream(params->stream); SIZE_T size; - if(params->timer_thread){ + if(stream->timer_thread){ stream->please_quit = TRUE; - NtWaitForSingleObject(params->timer_thread, FALSE, NULL); - NtClose(params->timer_thread); + NtWaitForSingleObject(stream->timer_thread, FALSE, NULL); + NtClose(stream->timer_thread); } snd_pcm_drop(stream->pcm_handle); @@ -1514,10 +1515,46 @@ static int alsa_rewind_best_effort(struct alsa_stream *stream) return len; } +static void alsa_timer_loop(void *args) +{ + struct alsa_stream *stream = args; + LARGE_INTEGER delay, next; + int adjust; + + alsa_lock(stream); + + delay.QuadPart = -stream->mmdev_period_rt; + NtQueryPerformanceCounter(&stream->last_period_time, NULL); + next.QuadPart = stream->last_period_time.QuadPart + stream->mmdev_period_rt; + + while(!stream->please_quit){ + if(stream->flow == eRender) + alsa_write_data(stream); + else if(stream->flow == eCapture) + alsa_read_data(stream); + alsa_unlock(stream); + + NtDelayExecution(FALSE, &delay); + + alsa_lock(stream); + NtQueryPerformanceCounter(&stream->last_period_time, NULL); + adjust = next.QuadPart - stream->last_period_time.QuadPart; + if(adjust > stream->mmdev_period_rt / 2) + adjust = stream->mmdev_period_rt / 2; + else if(adjust < -stream->mmdev_period_rt / 2) + adjust = -stream->mmdev_period_rt / 2; + delay.QuadPart = -(stream->mmdev_period_rt + adjust); + next.QuadPart += stream->mmdev_period_rt; + } + + alsa_unlock(stream); +} + static NTSTATUS alsa_start(void *args) { struct start_params *params = args; struct alsa_stream *stream = handle_get_stream(params->stream); + static const WCHAR name[] = {'a','u','d','i','o','_','c','l','i','e','n','t','_','t','i','m','e','r',0}; alsa_lock(stream); @@ -1555,6 +1592,7 @@ static NTSTATUS alsa_start(void *args) stream->data_in_alsa_frames = 0; } } + create_unix_thread( &stream->timer_thread, name, alsa_timer_loop, stream ); stream->started = TRUE; return alsa_unlock_result(stream, ¶ms->result, S_OK); @@ -1613,44 +1651,6 @@ static NTSTATUS alsa_reset(void *args) return alsa_unlock_result(stream, ¶ms->result, S_OK); } -static NTSTATUS alsa_timer_loop(void *args) -{ - struct timer_loop_params *params = args; - struct alsa_stream *stream = handle_get_stream(params->stream); - LARGE_INTEGER delay, next; - int adjust; - - alsa_lock(stream); - - delay.QuadPart = -stream->mmdev_period_rt; - NtQueryPerformanceCounter(&stream->last_period_time, NULL); - next.QuadPart = stream->last_period_time.QuadPart + stream->mmdev_period_rt; - - while(!stream->please_quit){ - if(stream->flow == eRender) - alsa_write_data(stream); - else if(stream->flow == eCapture) - alsa_read_data(stream); - alsa_unlock(stream); - - NtDelayExecution(FALSE, &delay); - - alsa_lock(stream); - NtQueryPerformanceCounter(&stream->last_period_time, NULL); - adjust = next.QuadPart - stream->last_period_time.QuadPart; - if(adjust > stream->mmdev_period_rt / 2) - adjust = stream->mmdev_period_rt / 2; - else if(adjust < -stream->mmdev_period_rt / 2) - adjust = -stream->mmdev_period_rt / 2; - delay.QuadPart = -(stream->mmdev_period_rt + adjust); - next.QuadPart += stream->mmdev_period_rt; - } - - alsa_unlock(stream); - - return STATUS_SUCCESS; -} - static NTSTATUS alsa_get_render_buffer(void *args) { struct get_render_buffer_params *params = args; @@ -2411,7 +2411,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = alsa_start, alsa_stop, alsa_reset, - alsa_timer_loop, alsa_get_render_buffer, alsa_release_render_buffer, alsa_get_capture_buffer, @@ -2520,13 +2519,11 @@ static NTSTATUS alsa_wow64_release_stream(void *args) struct { stream_handle stream; - PTR32 timer_thread; HRESULT result; } *params32 = args; struct release_stream_params params = { .stream = params32->stream, - .timer_thread = ULongToHandle(params32->timer_thread) }; alsa_release_stream(¶ms); params32->result = params.result; @@ -2865,7 +2862,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = alsa_start, alsa_stop, alsa_reset, - alsa_timer_loop, alsa_wow64_get_render_buffer, alsa_release_render_buffer, alsa_wow64_get_capture_buffer, diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index 78acef1c004..8c94e0ff82f 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -87,6 +87,7 @@ struct coreaudio_stream DWORD flags; AUDCLNT_SHAREMODE share; HANDLE event; + HANDLE timer_thread; BOOL playing, please_quit; REFERENCE_TIME period; @@ -810,10 +811,10 @@ static NTSTATUS unix_release_stream( void *args ) struct coreaudio_stream *stream = handle_get_stream(params->stream); SIZE_T size; - if(params->timer_thread){ + if(stream->timer_thread){ stream->please_quit = TRUE; - NtWaitForSingleObject(params->timer_thread, FALSE, NULL); - NtClose(params->timer_thread); + NtWaitForSingleObject(stream->timer_thread, FALSE, NULL); + NtClose(stream->timer_thread); } if(stream->unit){ @@ -1341,10 +1342,37 @@ static NTSTATUS unix_get_current_padding(void *args) return STATUS_SUCCESS; } +static void unix_timer_loop(void *args) +{ + struct coreaudio_stream *stream = args; + LARGE_INTEGER delay, next, last; + int adjust; + + delay.QuadPart = -stream->period; + NtQueryPerformanceCounter(&last, NULL); + next.QuadPart = last.QuadPart + stream->period; + + while(!stream->please_quit){ + NtSetEvent(stream->event, NULL); + NtDelayExecution(FALSE, &delay); + NtQueryPerformanceCounter(&last, NULL); + + adjust = next.QuadPart - last.QuadPart; + if(adjust > stream->period / 2) + adjust = stream->period / 2; + else if(adjust < -stream->period / 2) + adjust = -stream->period / 2; + + delay.QuadPart = -(stream->period + adjust); + next.QuadPart += stream->period; + } +} + static NTSTATUS unix_start(void *args) { struct start_params *params = args; struct coreaudio_stream *stream = handle_get_stream(params->stream); + static const WCHAR name[] = {'a','u','d','i','o','_','c','l','i','e','n','t','_','t','i','m','e','r',0}; os_unfair_lock_lock(&stream->lock); @@ -1358,6 +1386,7 @@ static NTSTATUS unix_start(void *args) } os_unfair_lock_unlock(&stream->lock); + create_unix_thread( &stream->timer_thread, name, unix_timer_loop, stream ); return STATUS_SUCCESS; } @@ -1409,35 +1438,6 @@ static NTSTATUS unix_reset(void *args) return STATUS_SUCCESS; } -static NTSTATUS unix_timer_loop(void *args) -{ - struct timer_loop_params *params = args; - struct coreaudio_stream *stream = handle_get_stream(params->stream); - LARGE_INTEGER delay, next, last; - int adjust; - - delay.QuadPart = -stream->period; - NtQueryPerformanceCounter(&last, NULL); - next.QuadPart = last.QuadPart + stream->period; - - while(!stream->please_quit){ - NtSetEvent(stream->event, NULL); - NtDelayExecution(FALSE, &delay); - NtQueryPerformanceCounter(&last, NULL); - - adjust = next.QuadPart - last.QuadPart; - if(adjust > stream->period / 2) - adjust = stream->period / 2; - else if(adjust < -stream->period / 2) - adjust = -stream->period / 2; - - delay.QuadPart = -(stream->period + adjust); - next.QuadPart += stream->period; - } - - return STATUS_SUCCESS; -} - static NTSTATUS unix_get_render_buffer(void *args) { struct get_render_buffer_params *params = args; @@ -1775,7 +1775,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = unix_start, unix_stop, unix_reset, - unix_timer_loop, unix_get_render_buffer, unix_release_render_buffer, unix_get_capture_buffer, @@ -1884,13 +1883,11 @@ static NTSTATUS unix_wow64_release_stream(void *args) struct { stream_handle stream; - PTR32 timer_thread; HRESULT result; } *params32 = args; struct release_stream_params params = { .stream = params32->stream, - .timer_thread = ULongToHandle(params32->timer_thread) }; unix_release_stream(¶ms); params32->result = params.result; @@ -2228,7 +2225,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = unix_start, unix_stop, unix_reset, - unix_timer_loop, unix_wow64_get_render_buffer, unix_release_render_buffer, unix_wow64_get_capture_buffer, diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c index 23ac761570f..54519427e6a 100644 --- a/dlls/wineoss.drv/oss.c +++ b/dlls/wineoss.drv/oss.c @@ -51,6 +51,7 @@ struct oss_stream UINT flags; AUDCLNT_SHAREMODE share; HANDLE event; + HANDLE timer_thread; int fd; @@ -632,10 +633,10 @@ static NTSTATUS oss_release_stream(void *args) struct oss_stream *stream = handle_get_stream(params->stream); SIZE_T size; - if(params->timer_thread){ + if(stream->timer_thread){ stream->please_quit = TRUE; - NtWaitForSingleObject(params->timer_thread, FALSE, NULL); - NtClose(params->timer_thread); + NtWaitForSingleObject(stream->timer_thread, FALSE, NULL); + NtClose(stream->timer_thread); } close(stream->fd); @@ -655,66 +656,6 @@ static NTSTATUS oss_release_stream(void *args) return STATUS_SUCCESS; } -static NTSTATUS oss_start(void *args) -{ - struct start_params *params = args; - struct oss_stream *stream = handle_get_stream(params->stream); - - oss_lock(stream); - - if((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event) - return oss_unlock_result(stream, ¶ms->result, AUDCLNT_E_EVENTHANDLE_NOT_SET); - - if(stream->playing) - return oss_unlock_result(stream, ¶ms->result, AUDCLNT_E_NOT_STOPPED); - - stream->playing = TRUE; - - return oss_unlock_result(stream, ¶ms->result, S_OK); -} - -static NTSTATUS oss_stop(void *args) -{ - struct stop_params *params = args; - struct oss_stream *stream = handle_get_stream(params->stream); - - oss_lock(stream); - - if(!stream->playing) - return oss_unlock_result(stream, ¶ms->result, S_FALSE); - - stream->playing = FALSE; - stream->in_oss_frames = 0; - - return oss_unlock_result(stream, ¶ms->result, S_OK); -} - -static NTSTATUS oss_reset(void *args) -{ - struct reset_params *params = args; - struct oss_stream *stream = handle_get_stream(params->stream); - - oss_lock(stream); - - if(stream->playing) - return oss_unlock_result(stream, ¶ms->result, AUDCLNT_E_NOT_STOPPED); - - if(stream->getbuf_last) - return oss_unlock_result(stream, ¶ms->result, AUDCLNT_E_BUFFER_OPERATION_PENDING); - - if(stream->flow == eRender){ - stream->written_frames = 0; - stream->last_pos_frames = 0; - }else{ - stream->written_frames += stream->held_frames; - } - stream->held_frames = 0; - stream->lcl_offs_frames = 0; - stream->in_oss_frames = 0; - - return oss_unlock_result(stream, ¶ms->result, S_OK); -} - static void silence_buffer(struct oss_stream *stream, BYTE *buffer, UINT32 frames) { WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)stream->fmt; @@ -862,10 +803,9 @@ static void oss_read_data(struct oss_stream *stream) } } -static NTSTATUS oss_timer_loop(void *args) +static void oss_timer_loop(void *args) { - struct timer_loop_params *params = args; - struct oss_stream *stream = handle_get_stream(params->stream); + struct oss_stream *stream = args; LARGE_INTEGER delay, now, next; int adjust; @@ -900,8 +840,68 @@ static NTSTATUS oss_timer_loop(void *args) } oss_unlock(stream); +} - return STATUS_SUCCESS; +static NTSTATUS oss_start(void *args) +{ + struct start_params *params = args; + struct oss_stream *stream = handle_get_stream(params->stream); + static const WCHAR name[] = {'a','u','d','i','o','_','c','l','i','e','n','t','_','t','i','m','e','r',0}; + + oss_lock(stream); + + if((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event) + return oss_unlock_result(stream, ¶ms->result, AUDCLNT_E_EVENTHANDLE_NOT_SET); + + if(stream->playing) + return oss_unlock_result(stream, ¶ms->result, AUDCLNT_E_NOT_STOPPED); + + stream->playing = TRUE; + create_unix_thread( &stream->timer_thread, name, oss_timer_loop, stream ); + + return oss_unlock_result(stream, ¶ms->result, S_OK); +} + +static NTSTATUS oss_stop(void *args) +{ + struct stop_params *params = args; + struct oss_stream *stream = handle_get_stream(params->stream); + + oss_lock(stream); + + if(!stream->playing) + return oss_unlock_result(stream, ¶ms->result, S_FALSE); + + stream->playing = FALSE; + stream->in_oss_frames = 0; + + return oss_unlock_result(stream, ¶ms->result, S_OK); +} + +static NTSTATUS oss_reset(void *args) +{ + struct reset_params *params = args; + struct oss_stream *stream = handle_get_stream(params->stream); + + oss_lock(stream); + + if(stream->playing) + return oss_unlock_result(stream, ¶ms->result, AUDCLNT_E_NOT_STOPPED); + + if(stream->getbuf_last) + return oss_unlock_result(stream, ¶ms->result, AUDCLNT_E_BUFFER_OPERATION_PENDING); + + if(stream->flow == eRender){ + stream->written_frames = 0; + stream->last_pos_frames = 0; + }else{ + stream->written_frames += stream->held_frames; + } + stream->held_frames = 0; + stream->lcl_offs_frames = 0; + stream->in_oss_frames = 0; + + return oss_unlock_result(stream, ¶ms->result, S_OK); } static NTSTATUS oss_get_render_buffer(void *args) @@ -1642,7 +1642,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = oss_start, oss_stop, oss_reset, - oss_timer_loop, oss_get_render_buffer, oss_release_render_buffer, oss_get_capture_buffer, @@ -1767,13 +1766,11 @@ static NTSTATUS oss_wow64_release_stream(void *args) struct { stream_handle stream; - PTR32 timer_thread; HRESULT result; } *params32 = args; struct release_stream_params params = { .stream = params32->stream, - .timer_thread = ULongToHandle(params32->timer_thread) }; oss_release_stream(¶ms); params32->result = params.result; @@ -2135,7 +2132,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = oss_start, oss_stop, oss_reset, - oss_timer_loop, oss_wow64_get_render_buffer, oss_release_render_buffer, oss_wow64_get_capture_buffer, diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 66a453e5a69..bdf75181997 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -65,6 +65,7 @@ struct pulse_stream DWORD flags; AUDCLNT_SHAREMODE share; HANDLE event; + HANDLE timer_thread; float vol[PA_CHANNELS_MAX]; REFERENCE_TIME def_period; @@ -1261,10 +1262,10 @@ static NTSTATUS pulse_release_stream(void *args) struct pulse_stream *stream = handle_get_stream(params->stream); SIZE_T size; - if(params->timer_thread) { + if(stream->timer_thread) { stream->please_quit = TRUE; - NtWaitForSingleObject(params->timer_thread, FALSE, NULL); - NtClose(params->timer_thread); + NtWaitForSingleObject(stream->timer_thread, FALSE, NULL); + NtClose(stream->timer_thread); } pulse_lock(); @@ -1576,10 +1577,9 @@ static void pulse_read(struct pulse_stream *stream) } } -static NTSTATUS pulse_timer_loop(void *args) +static void pulse_timer_loop(void *args) { - struct timer_loop_params *params = args; - struct pulse_stream *stream = handle_get_stream(params->stream); + struct pulse_stream *stream = args; LARGE_INTEGER delay; pa_usec_t last_time; UINT32 adv_bytes; @@ -1673,14 +1673,13 @@ static NTSTATUS pulse_timer_loop(void *args) pulse_unlock(); } - - return STATUS_SUCCESS; } static NTSTATUS pulse_start(void *args) { struct start_params *params = args; struct pulse_stream *stream = handle_get_stream(params->stream); + static const WCHAR name[] = {'a','u','d','i','o','_','c','l','i','e','n','t','_','t','i','m','e','r',0}; int success; params->result = S_OK; @@ -1722,6 +1721,7 @@ static NTSTATUS pulse_start(void *args) stream->just_started = TRUE; } pulse_unlock(); + create_unix_thread( &stream->timer_thread, name, pulse_timer_loop, stream ); return STATUS_SUCCESS; } @@ -2540,7 +2540,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = pulse_start, pulse_stop, pulse_reset, - pulse_timer_loop, pulse_get_render_buffer, pulse_release_render_buffer, pulse_get_capture_buffer, @@ -2650,13 +2649,11 @@ static NTSTATUS pulse_wow64_release_stream(void *args) struct { stream_handle stream; - PTR32 timer_thread; HRESULT result; } *params32 = args; struct release_stream_params params = { .stream = params32->stream, - .timer_thread = ULongToHandle(params32->timer_thread) }; pulse_release_stream(¶ms); params32->result = params.result; @@ -3035,7 +3032,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = pulse_start, pulse_stop, pulse_reset, - pulse_timer_loop, pulse_wow64_get_render_buffer, pulse_release_render_buffer, pulse_wow64_get_capture_buffer, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10912