winealsa: Move start to the unixlib.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2022-03-02 10:53:17 +00:00 committed by Alexandre Julliard
parent c32898c722
commit 1420d247a2
3 changed files with 59 additions and 111 deletions

View File

@ -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, &params->result, AUDCLNT_E_EVENTHANDLE_NOT_SET);
if(stream->started)
return alsa_unlock_result(stream, &params->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, &params->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 */
};

View File

@ -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, &params);
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, &params);
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)

View File

@ -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;