diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index d455a3787e8..a5558718f47 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -1214,13 +1214,6 @@ static snd_pcm_sframes_t alsa_write_best_effort(struct alsa_stream *stream, BYTE return written; } -static NTSTATUS write_best_effort(void *args) -{ - struct write_best_effort_tmp_params *params = args; - *params->written = alsa_write_best_effort(params->stream, params->buf, params->frames); - return STATUS_SUCCESS; -} - static snd_pcm_sframes_t alsa_write_buffer_wrap(struct alsa_stream *stream, BYTE *buf, snd_pcm_uframes_t buflen, snd_pcm_uframes_t offs, snd_pcm_uframes_t to_write) @@ -1416,6 +1409,52 @@ exit: NtSetEvent(stream->event, NULL); } +static NTSTATUS start(void *args) +{ + struct start_params *params = args; + struct alsa_stream *stream = params->stream; + + alsa_lock(stream); + + if((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event) + return alsa_unlock_result(stream, ¶ms->result, AUDCLNT_E_EVENTHANDLE_NOT_SET); + + if(stream->started) + return alsa_unlock_result(stream, ¶ms->result, AUDCLNT_E_NOT_STOPPED); + + if(stream->flow == eCapture){ + /* dump any data that might be leftover in the ALSA capture buffer */ + snd_pcm_readi(stream->pcm_handle, stream->local_buffer, + stream->bufsize_frames); + }else{ + snd_pcm_sframes_t avail, written; + snd_pcm_uframes_t offs; + + avail = snd_pcm_avail_update(stream->pcm_handle); + avail = min(avail, stream->held_frames); + + if(stream->wri_offs_frames < stream->held_frames) + offs = stream->bufsize_frames - stream->held_frames + stream->wri_offs_frames; + else + offs = stream->wri_offs_frames - stream->held_frames; + + /* fill it with data */ + written = alsa_write_buffer_wrap(stream, stream->local_buffer, + stream->bufsize_frames, offs, avail); + + if(written > 0){ + stream->lcl_offs_frames = (offs + written) % stream->bufsize_frames; + stream->data_in_alsa_frames = written; + }else{ + stream->lcl_offs_frames = offs; + stream->data_in_alsa_frames = 0; + } + } + stream->started = TRUE; + + return alsa_unlock_result(stream, ¶ms->result, S_OK); +} + static NTSTATUS timer_loop(void *args) { struct timer_loop_params *params = args; @@ -1761,12 +1800,11 @@ unixlib_entry_t __wine_unix_call_funcs[] = get_endpoint_ids, create_stream, release_stream, + start, timer_loop, is_format_supported, get_mix_format, get_buffer_size, get_latency, get_current_padding, - - write_best_effort /* temporary */ }; diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index 2748cc552a6..5eab548e606 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -963,51 +963,6 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface, return S_OK; } -static snd_pcm_sframes_t alsa_write_best_effort(struct alsa_stream *stream, BYTE *buf, snd_pcm_uframes_t frames) -{ - struct write_best_effort_tmp_params params; - snd_pcm_sframes_t written; - - params.stream = stream; - params.buf = buf; - params.frames = frames; - params.written = &written; - - ALSA_CALL(write_best_effort_tmp, ¶ms); - - return written; -} - -static snd_pcm_sframes_t alsa_write_buffer_wrap(struct alsa_stream *stream, BYTE *buf, - snd_pcm_uframes_t buflen, snd_pcm_uframes_t offs, - snd_pcm_uframes_t to_write) -{ - snd_pcm_sframes_t ret = 0; - - while(to_write){ - snd_pcm_uframes_t chunk; - snd_pcm_sframes_t tmp; - - if(offs + to_write > buflen) - chunk = buflen - offs; - else - chunk = to_write; - - tmp = alsa_write_best_effort(stream, buf + offs * stream->fmt->nBlockAlign, chunk); - if(tmp < 0) - return ret; - if(!tmp) - break; - - ret += tmp; - to_write -= tmp; - offs += tmp; - offs %= buflen; - } - - return ret; -} - static snd_pcm_uframes_t interp_elapsed_frames(struct alsa_stream *stream) { LARGE_INTEGER time_freq, current_time, time_diff; @@ -1053,7 +1008,7 @@ static int alsa_rewind_best_effort(ACImpl *This) static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface) { ACImpl *This = impl_from_IAudioClient3(iface); - struct alsa_stream *stream = This->stream; + struct start_params params; TRACE("(%p)\n", This); @@ -1064,60 +1019,18 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface) return AUDCLNT_E_NOT_INITIALIZED; } - alsa_lock(stream); + params.stream = This->stream; - if((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event){ - alsa_unlock(stream); - LeaveCriticalSection(&g_sessions_lock); - return AUDCLNT_E_EVENTHANDLE_NOT_SET; - } + ALSA_CALL(start, ¶ms); - if(stream->started){ - alsa_unlock(stream); - LeaveCriticalSection(&g_sessions_lock); - return AUDCLNT_E_NOT_STOPPED; - } - - if(stream->flow == eCapture){ - /* dump any data that might be leftover in the ALSA capture buffer */ - snd_pcm_readi(stream->pcm_handle, stream->local_buffer, - stream->bufsize_frames); - }else{ - snd_pcm_sframes_t avail, written; - snd_pcm_uframes_t offs; - - avail = snd_pcm_avail_update(stream->pcm_handle); - avail = min(avail, stream->held_frames); - - if(stream->wri_offs_frames < stream->held_frames) - offs = stream->bufsize_frames - stream->held_frames + stream->wri_offs_frames; - else - offs = stream->wri_offs_frames - stream->held_frames; - - /* fill it with data */ - written = alsa_write_buffer_wrap(stream, stream->local_buffer, - stream->bufsize_frames, offs, avail); - - if(written > 0){ - stream->lcl_offs_frames = (offs + written) % stream->bufsize_frames; - stream->data_in_alsa_frames = written; - }else{ - stream->lcl_offs_frames = offs; - stream->data_in_alsa_frames = 0; - } - } - - if(!This->timer_thread){ + if(SUCCEEDED(params.result) && !This->timer_thread){ This->timer_thread = CreateThread(NULL, 0, alsa_timer_thread, This->stream, 0, NULL); SetThreadPriority(This->timer_thread, THREAD_PRIORITY_TIME_CRITICAL); } - stream->started = TRUE; - - alsa_unlock(stream); LeaveCriticalSection(&g_sessions_lock); - return S_OK; + return params.result; } static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface) diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h index 4acbbcbcf11..c058a920b6e 100644 --- a/dlls/winealsa.drv/unixlib.h +++ b/dlls/winealsa.drv/unixlib.h @@ -91,6 +91,12 @@ struct release_stream_params HRESULT result; }; +struct start_params +{ + struct alsa_stream *stream; + HRESULT result; +}; + struct timer_loop_params { struct alsa_stream *stream; @@ -135,27 +141,18 @@ struct get_current_padding_params UINT32 *padding; }; -struct write_best_effort_tmp_params -{ - struct alsa_stream *stream; - BYTE *buf; - snd_pcm_uframes_t frames; - snd_pcm_sframes_t *written; -}; - enum alsa_funcs { alsa_get_endpoint_ids, alsa_create_stream, alsa_release_stream, + alsa_start, alsa_timer_loop, alsa_is_format_supported, alsa_get_mix_format, alsa_get_buffer_size, alsa_get_latency, alsa_get_current_padding, - - alsa_write_best_effort_tmp }; extern unixlib_handle_t alsa_handle;