[PATCH v3 0/2] MR10912: mmdevapi: Use system threads for audio driver internal threads.
-- v3: mmdevapi: Use a system thread for the audio driver timer loop thread. mmdevapi: Use a system thread for the audio driver main loop thread. https://gitlab.winehq.org/wine/wine/-/merge_requests/10912
From: Alexandre Julliard <julliard@winehq.org> --- dlls/mmdevapi/client.c | 46 +------------------------- dlls/mmdevapi/main.c | 2 +- dlls/mmdevapi/mmdevapi_private.h | 2 -- dlls/mmdevapi/unixlib.h | 27 +++++++++++---- dlls/winealsa.drv/alsa.c | 26 +++------------ dlls/winecoreaudio.drv/coreaudio.c | 26 +++------------ dlls/wineoss.drv/oss.c | 26 +++------------ dlls/winepulse.drv/pulse.c | 53 ++++++++++++++++++++---------- 8 files changed, 70 insertions(+), 138 deletions(-) diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index d7e05a68215..25ba520de48 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -42,16 +42,6 @@ typedef struct tagLANGANDCODEPAGE WORD wCodePage; } LANGANDCODEPAGE; -static HANDLE main_loop_thread; - -void main_loop_stop(void) -{ - if (main_loop_thread) { - WaitForSingleObject(main_loop_thread, INFINITE); - CloseHandle(main_loop_thread); - } -} - void set_stream_volumes(struct audio_client *This) { struct set_volumes_params params; @@ -202,37 +192,6 @@ static void dump_fmt(const WAVEFORMATEX *fmt) } } -static DWORD CALLBACK main_loop_func(void *event) -{ - struct main_loop_params params; - - SetThreadDescription(GetCurrentThread(), L"audio_client_main"); - - params.event = event; - - wine_unix_call(main_loop, ¶ms); - - return 0; -} - -HRESULT main_loop_start(void) -{ - if (!main_loop_thread) { - HANDLE event = CreateEventW(NULL, TRUE, FALSE, NULL); - if (!(main_loop_thread = CreateThread(NULL, 0, main_loop_func, event, 0, NULL))) { - ERR("Failed to create main loop thread\n"); - CloseHandle(event); - return E_FAIL; - } - - SetThreadPriority(main_loop_thread, THREAD_PRIORITY_TIME_CRITICAL); - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - } - - return S_OK; -} - static DWORD CALLBACK timer_loop_func(void *user) { struct timer_loop_params params; @@ -503,10 +462,7 @@ static HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_ return AUDCLNT_E_ALREADY_INITIALIZED; } - if (FAILED(params.result = main_loop_start())) { - sessions_unlock(); - return params.result; - } + wine_unix_call( main_loop_start, NULL ); if (flags & AUDCLNT_STREAMFLAGS_LOOPBACK) { struct get_loopback_capture_device_params params; diff --git a/dlls/mmdevapi/main.c b/dlls/mmdevapi/main.c index 21b46b988f1..70eace863e1 100644 --- a/dlls/mmdevapi/main.c +++ b/dlls/mmdevapi/main.c @@ -211,7 +211,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) } if (lpvReserved) break; - main_loop_stop(); + wine_unix_call( main_loop_stop, NULL ); if (drvs.module_unixlib) { __wine_unload_unix_lib( drvs.module ); diff --git a/dlls/mmdevapi/mmdevapi_private.h b/dlls/mmdevapi/mmdevapi_private.h index acd3baa8cc4..6a04e9077ef 100644 --- a/dlls/mmdevapi/mmdevapi_private.h +++ b/dlls/mmdevapi/mmdevapi_private.h @@ -129,8 +129,6 @@ extern BOOL get_device_name_from_guid( const GUID *guid, char **name, EDataFlow extern HRESULT load_devices_from_reg(void); extern HRESULT load_driver_devices(EDataFlow flow); -extern void main_loop_stop(void); - extern const WCHAR drv_keyW[]; extern HRESULT get_audio_session(const GUID *sessionguid, IMMDevice *device, UINT channels, diff --git a/dlls/mmdevapi/unixlib.h b/dlls/mmdevapi/unixlib.h index 3df13e93b39..c46a4ff4e98 100644 --- a/dlls/mmdevapi/unixlib.h +++ b/dlls/mmdevapi/unixlib.h @@ -20,6 +20,25 @@ #include "audioclient.h" #include "mmdeviceapi.h" +#ifdef WINE_UNIX_LIB +/* helper to create a thread on the Unix side */ +static inline NTSTATUS create_unix_thread( HANDLE *handle, const WCHAR *name, + void (*entry)(void *), void *param ) +{ + DWORD priority = THREAD_PRIORITY_TIME_CRITICAL; + THREAD_NAME_INFORMATION info; + NTSTATUS status; + + if (!(status = PsCreateSystemThread( handle, THREAD_ALL_ACCESS, NULL, 0, NULL, entry, param ))) + { + RtlInitUnicodeString( &info.ThreadName, name ); + NtSetInformationThread( *handle, ThreadNameInformation, &info, sizeof(info) ); + NtSetInformationThread( *handle, ThreadBasePriority, &priority, sizeof(priority) ); + } + return status; +} +#endif + typedef UINT64 stream_handle; enum driver_priority @@ -36,11 +55,6 @@ struct endpoint unsigned int device; }; -struct main_loop_params -{ - HANDLE event; -}; - struct get_endpoint_ids_params { EDataFlow flow; @@ -315,7 +329,8 @@ enum unix_funcs { process_attach, process_detach, - main_loop, + main_loop_start, + main_loop_stop, get_endpoint_ids, create_stream, release_stream, diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index e7c93116fd1..9497c06059c 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -477,13 +477,6 @@ static WCHAR *alsa_get_card_name(int card) return ret; } -static NTSTATUS alsa_main_loop(void *args) -{ - struct main_loop_params *params = args; - NtSetEvent(params->event, NULL); - return STATUS_SUCCESS; -} - static NTSTATUS alsa_get_endpoint_ids(void *args) { static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0}; @@ -2410,7 +2403,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { alsa_not_implemented, alsa_not_implemented, - alsa_main_loop, + alsa_not_implemented, + alsa_not_implemented, alsa_get_endpoint_ids, alsa_create_stream, alsa_release_stream, @@ -2462,19 +2456,6 @@ static NTSTATUS alsa_wow64_process_attach(void *args) return STATUS_SUCCESS; } -static NTSTATUS alsa_wow64_main_loop(void *args) -{ - struct - { - PTR32 event; - } *params32 = args; - struct main_loop_params params = - { - .event = ULongToHandle(params32->event) - }; - return alsa_main_loop(¶ms); -} - static NTSTATUS alsa_wow64_get_endpoint_ids(void *args) { struct @@ -2876,7 +2857,8 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { alsa_wow64_process_attach, alsa_not_implemented, - alsa_wow64_main_loop, + alsa_not_implemented, + alsa_not_implemented, alsa_wow64_get_endpoint_ids, alsa_wow64_create_stream, alsa_wow64_release_stream, diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c index a4f78f6d6bb..78acef1c004 100644 --- a/dlls/winecoreaudio.drv/coreaudio.c +++ b/dlls/winecoreaudio.drv/coreaudio.c @@ -199,13 +199,6 @@ static BOOL device_has_channels(AudioDeviceID device, EDataFlow flow) return ret; } -static NTSTATUS unix_main_loop(void *args) -{ - struct main_loop_params *params = args; - NtSetEvent(params->event, NULL); - return STATUS_SUCCESS; -} - static NTSTATUS unix_get_endpoint_ids(void *args) { struct get_endpoint_ids_params *params = args; @@ -1774,7 +1767,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { unix_not_implemented, unix_not_implemented, - unix_main_loop, + unix_not_implemented, + unix_not_implemented, unix_get_endpoint_ids, unix_create_stream, unix_release_stream, @@ -1826,19 +1820,6 @@ static NTSTATUS unix_wow64_process_attach(void *args) return STATUS_SUCCESS; } -static NTSTATUS unix_wow64_main_loop(void *args) -{ - struct - { - PTR32 event; - } *params32 = args; - struct main_loop_params params = - { - .event = ULongToHandle(params32->event) - }; - return unix_main_loop(¶ms); -} - static NTSTATUS unix_wow64_get_endpoint_ids(void *args) { struct @@ -2239,7 +2220,8 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { unix_wow64_process_attach, unix_not_implemented, - unix_wow64_main_loop, + unix_not_implemented, + unix_not_implemented, unix_wow64_get_endpoint_ids, unix_wow64_create_stream, unix_wow64_release_stream, diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c index 4136edf4fd8..23ac761570f 100644 --- a/dlls/wineoss.drv/oss.c +++ b/dlls/wineoss.drv/oss.c @@ -222,13 +222,6 @@ static void get_default_device(EDataFlow flow, char device[OSS_DEVNODE_SIZE]) return; } -static NTSTATUS oss_main_loop(void *args) -{ - struct main_loop_params *params = args; - NtSetEvent(params->event, NULL); - return STATUS_SUCCESS; -} - static NTSTATUS oss_get_endpoint_ids(void *args) { struct get_endpoint_ids_params *params = args; @@ -1641,7 +1634,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { oss_not_implemented, oss_not_implemented, - oss_main_loop, + oss_not_implemented, + oss_not_implemented, oss_get_endpoint_ids, oss_create_stream, oss_release_stream, @@ -1709,19 +1703,6 @@ static NTSTATUS oss_wow64_test_connect(void *args) return STATUS_SUCCESS; } -static NTSTATUS oss_wow64_main_loop(void *args) -{ - struct - { - PTR32 event; - } *params32 = args; - struct main_loop_params params = - { - .event = ULongToHandle(params32->event) - }; - return oss_main_loop(¶ms); -} - static NTSTATUS oss_wow64_get_endpoint_ids(void *args) { struct @@ -2146,7 +2127,8 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { oss_wow64_process_attach, oss_not_implemented, - oss_wow64_main_loop, + oss_not_implemented, + oss_not_implemented, oss_wow64_get_endpoint_ids, oss_wow64_create_stream, oss_wow64_release_stream, diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index fdae8ecc36a..66a453e5a69 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -273,19 +273,47 @@ static void pulse_main_loop_thread_cleanup(void *context) pulse_broadcast(); } -static NTSTATUS pulse_main_loop(void *args) +static void pulse_main_loop(void *args) { - struct main_loop_params *params = args; + HANDLE event = args; int ret; pulse_lock(); pulse_ml = pa_mainloop_new(); pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL); - NtSetEvent(params->event, NULL); + NtSetEvent(event, NULL); pthread_cleanup_push(pulse_main_loop_thread_cleanup, NULL); pa_mainloop_run(pulse_ml, &ret); pthread_cleanup_pop(0); pa_mainloop_free(pulse_ml); pulse_unlock(); + PsTerminateSystemThread( 0 ); +} + +static HANDLE main_loop_thread; + +static NTSTATUS pulse_main_loop_start(void *args) +{ + static const WCHAR name[] = {'a','u','d','i','o','_','c','l','i','e','n','t','_','m','a','i','n',0}; + HANDLE event; + NTSTATUS status; + + if (main_loop_thread) return STATUS_SUCCESS; + + NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE ); + if (!(status = create_unix_thread( &main_loop_thread, name, pulse_main_loop, event ))) + NtWaitForSingleObject( event, FALSE, NULL ); + NtClose( event ); + return status; +} + +static NTSTATUS pulse_main_loop_stop(void *args) +{ + if (main_loop_thread) + { + NtWaitForSingleObject( main_loop_thread, FALSE, NULL ); + NtClose( main_loop_thread ); + main_loop_thread = 0; + } return STATUS_SUCCESS; } @@ -2504,7 +2532,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { pulse_process_attach, pulse_process_detach, - pulse_main_loop, + pulse_main_loop_start, + pulse_main_loop_stop, pulse_get_endpoint_ids, pulse_create_stream, pulse_release_stream, @@ -2557,19 +2586,6 @@ static NTSTATUS pulse_wow64_process_attach(void *args) return pulse_process_attach( args ); } -static NTSTATUS pulse_wow64_main_loop(void *args) -{ - struct - { - PTR32 event; - } *params32 = args; - struct main_loop_params params = - { - .event = ULongToHandle(params32->event) - }; - return pulse_main_loop(¶ms); -} - static NTSTATUS pulse_wow64_get_endpoint_ids(void *args) { struct @@ -3011,7 +3027,8 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { pulse_wow64_process_attach, pulse_process_detach, - pulse_wow64_main_loop, + pulse_main_loop_start, + pulse_main_loop_stop, pulse_wow64_get_endpoint_ids, pulse_wow64_create_stream, pulse_wow64_release_stream, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10912
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..4ad83bdba05 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; } } + if (!stream->timer_thread) 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..c7e0dc24048 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); + if (!stream->timer_thread) 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..431264faf31 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; + if (!stream->timer_thread) 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..ef13a1ed0bb 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(); + if (!stream->timer_thread) 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
It should be good now. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10912#note_140454
This merge request was approved by Huw Davies. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10912
participants (3)
-
Alexandre Julliard -
Alexandre Julliard (@julliard) -
Huw Davies (@huw)