[PATCH 3/8] winealsa: Introduce a stream structure.
Andrew Eikum
aeikum at codeweavers.com
Thu Feb 17 09:25:24 CST 2022
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Wed, Feb 16, 2022 at 09:34:49AM +0000, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
> dlls/winealsa.drv/mmdevdrv.c | 691 ++++++++++++++++++-----------------
> dlls/winealsa.drv/unixlib.h | 35 ++
> 2 files changed, 385 insertions(+), 341 deletions(-)
>
> diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
> index 0549752dc3f..f1bc2fd0247 100644
> --- a/dlls/winealsa.drv/mmdevdrv.c
> +++ b/dlls/winealsa.drv/mmdevdrv.c
> @@ -101,42 +101,17 @@ struct ACImpl {
>
> LONG ref;
>
> - snd_pcm_t *pcm_handle;
> - snd_pcm_uframes_t alsa_bufsize_frames, alsa_period_frames, safe_rewind_frames;
> - snd_pcm_hw_params_t *hw_params; /* does not hold state between calls */
> - snd_pcm_format_t alsa_format;
> -
> - LARGE_INTEGER last_period_time;
> -
> IMMDevice *parent;
> IUnknown *pUnkFTMarshal;
>
> EDataFlow dataflow;
> - WAVEFORMATEX *fmt;
> - DWORD flags;
> - AUDCLNT_SHAREMODE share;
> - HANDLE event;
> float *vols;
> UINT32 channel_count;
> + struct alsa_stream *stream;
>
> - BOOL need_remapping;
> - int alsa_channels;
> - int alsa_channel_map[32];
> -
> - BOOL initted, started;
> - REFERENCE_TIME mmdev_period_rt;
> - UINT64 written_frames, last_pos_frames;
> - UINT32 bufsize_frames, held_frames, tmp_buffer_frames, mmdev_period_frames;
> - snd_pcm_uframes_t remapping_buf_frames;
> - UINT32 lcl_offs_frames; /* offs into local_buffer where valid data starts */
> - UINT32 wri_offs_frames; /* where to write fresh data in local_buffer */
> - UINT32 hidden_frames; /* ALSA reserve to ensure continuous rendering */
> - UINT32 vol_adjusted_frames; /* Frames we've already adjusted the volume of but didn't write yet */
> - UINT32 data_in_alsa_frames;
> + BOOL initted;
>
> HANDLE timer;
> - BYTE *local_buffer, *tmp_buffer, *remapping_buf, *silence_buf;
> - LONG32 getbuf_last; /* <0 when using tmp_buffer */
>
> CRITICAL_SECTION lock;
>
> @@ -505,8 +480,15 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
> This->dataflow = dataflow;
> memcpy(This->alsa_name, alsa_name, len + 1);
>
> - err = snd_pcm_open(&This->pcm_handle, alsa_name, alsa_get_direction(dataflow), SND_PCM_NONBLOCK);
> + This->stream = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->stream));
> + if(!This->stream){
> + HeapFree(GetProcessHeap(), 0, This);
> + return E_OUTOFMEMORY;
> + }
> +
> + err = snd_pcm_open(&This->stream->pcm_handle, alsa_name, alsa_get_direction(dataflow), SND_PCM_NONBLOCK);
> if(err < 0){
> + HeapFree(GetProcessHeap(), 0, This->stream);
> HeapFree(GetProcessHeap(), 0, This);
> WARN("Unable to open PCM \"%s\": %d (%s)\n", alsa_name, err, snd_strerror(err));
> switch(err){
> @@ -517,10 +499,11 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
> }
> }
>
> - This->hw_params = HeapAlloc(GetProcessHeap(), 0,
> + This->stream->hw_params = HeapAlloc(GetProcessHeap(), 0,
> snd_pcm_hw_params_sizeof());
> - if(!This->hw_params){
> - snd_pcm_close(This->pcm_handle);
> + if(!This->stream->hw_params){
> + snd_pcm_close(This->stream->pcm_handle);
> + HeapFree(GetProcessHeap(), 0, This->stream);
> HeapFree(GetProcessHeap(), 0, This);
> return E_OUTOFMEMORY;
> }
> @@ -574,6 +557,7 @@ static ULONG WINAPI AudioClient_AddRef(IAudioClient3 *iface)
> static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
> {
> ACImpl *This = impl_from_IAudioClient3(iface);
> + struct alsa_stream *stream = This->stream;
> ULONG ref;
>
> ref = InterlockedDecrement(&This->ref);
> @@ -595,20 +579,21 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
> IUnknown_Release(This->pUnkFTMarshal);
> This->lock.DebugInfo->Spare[0] = 0;
> DeleteCriticalSection(&This->lock);
> - snd_pcm_drop(This->pcm_handle);
> - snd_pcm_close(This->pcm_handle);
> + snd_pcm_drop(stream->pcm_handle);
> + snd_pcm_close(stream->pcm_handle);
> if(This->initted){
> EnterCriticalSection(&g_sessions_lock);
> list_remove(&This->entry);
> LeaveCriticalSection(&g_sessions_lock);
> }
> HeapFree(GetProcessHeap(), 0, This->vols);
> - HeapFree(GetProcessHeap(), 0, This->local_buffer);
> - HeapFree(GetProcessHeap(), 0, This->remapping_buf);
> - HeapFree(GetProcessHeap(), 0, This->silence_buf);
> - HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
> - HeapFree(GetProcessHeap(), 0, This->hw_params);
> - CoTaskMemFree(This->fmt);
> + HeapFree(GetProcessHeap(), 0, stream->local_buffer);
> + HeapFree(GetProcessHeap(), 0, stream->remapping_buf);
> + HeapFree(GetProcessHeap(), 0, stream->silence_buf);
> + HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
> + HeapFree(GetProcessHeap(), 0, stream->hw_params);
> + CoTaskMemFree(stream->fmt);
> + HeapFree(GetProcessHeap(), 0, stream);
> HeapFree(GetProcessHeap(), 0, This);
> }
> return ref;
> @@ -904,16 +889,16 @@ static HRESULT map_channels(ACImpl *This, const WAVEFORMATEX *fmt, int *alsa_cha
> return need_remap ? S_OK : S_FALSE;
> }
>
> -static void silence_buffer(ACImpl *This, BYTE *buffer, UINT32 frames)
> +static void silence_buffer(struct alsa_stream *stream, BYTE *buffer, UINT32 frames)
> {
> - WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)This->fmt;
> - if((This->fmt->wFormatTag == WAVE_FORMAT_PCM ||
> - (This->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> + WAVEFORMATEXTENSIBLE *fmtex = (WAVEFORMATEXTENSIBLE*)stream->fmt;
> + if((stream->fmt->wFormatTag == WAVE_FORMAT_PCM ||
> + (stream->fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) &&
> - This->fmt->wBitsPerSample == 8)
> - memset(buffer, 128, frames * This->fmt->nBlockAlign);
> + stream->fmt->wBitsPerSample == 8)
> + memset(buffer, 128, frames * stream->fmt->nBlockAlign);
> else
> - memset(buffer, 0, frames * This->fmt->nBlockAlign);
> + memset(buffer, 0, frames * stream->fmt->nBlockAlign);
> }
>
> static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
> @@ -922,6 +907,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
> const GUID *sessionguid)
> {
> ACImpl *This = impl_from_IAudioClient3(iface);
> + struct alsa_stream *stream = This->stream;
> snd_pcm_sw_params_t *sw_params = NULL;
> snd_pcm_format_t format;
> unsigned int rate, alsa_period_us;
> @@ -990,15 +976,15 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>
> dump_fmt(fmt);
>
> - This->need_remapping = map_channels(This, fmt, &This->alsa_channels, This->alsa_channel_map) == S_OK;
> + stream->need_remapping = map_channels(This, fmt, &stream->alsa_channels, stream->alsa_channel_map) == S_OK;
>
> - if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
> + if((err = snd_pcm_hw_params_any(stream->pcm_handle, stream->hw_params)) < 0){
> WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_set_access(This->pcm_handle, This->hw_params,
> + if((err = snd_pcm_hw_params_set_access(stream->pcm_handle, stream->hw_params,
> SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
> WARN("Unable to set access: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> @@ -1011,7 +997,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_set_format(This->pcm_handle, This->hw_params,
> + if((err = snd_pcm_hw_params_set_format(stream->pcm_handle, stream->hw_params,
> format)) < 0){
> WARN("Unable to set ALSA format to %u: %d (%s)\n", format, err,
> snd_strerror(err));
> @@ -1019,10 +1005,10 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
> goto exit;
> }
>
> - This->alsa_format = format;
> + stream->alsa_format = format;
>
> rate = fmt->nSamplesPerSec;
> - if((err = snd_pcm_hw_params_set_rate_near(This->pcm_handle, This->hw_params,
> + if((err = snd_pcm_hw_params_set_rate_near(stream->pcm_handle, stream->hw_params,
> &rate, NULL)) < 0){
> WARN("Unable to set rate to %u: %d (%s)\n", rate, err,
> snd_strerror(err));
> @@ -1030,52 +1016,52 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_set_channels(This->pcm_handle, This->hw_params,
> - This->alsa_channels)) < 0){
> + if((err = snd_pcm_hw_params_set_channels(stream->pcm_handle, stream->hw_params,
> + stream->alsa_channels)) < 0){
> WARN("Unable to set channels to %u: %d (%s)\n", fmt->nChannels, err,
> snd_strerror(err));
> hr = AUDCLNT_E_UNSUPPORTED_FORMAT;
> goto exit;
> }
>
> - This->mmdev_period_rt = period;
> - alsa_period_us = This->mmdev_period_rt / 10;
> - if((err = snd_pcm_hw_params_set_period_time_near(This->pcm_handle,
> - This->hw_params, &alsa_period_us, NULL)) < 0)
> + stream->mmdev_period_rt = period;
> + alsa_period_us = stream->mmdev_period_rt / 10;
> + if((err = snd_pcm_hw_params_set_period_time_near(stream->pcm_handle,
> + stream->hw_params, &alsa_period_us, NULL)) < 0)
> WARN("Unable to set period time near %u: %d (%s)\n", alsa_period_us,
> err, snd_strerror(err));
> /* ALSA updates the output variable alsa_period_us */
>
> - This->mmdev_period_frames = MulDiv(fmt->nSamplesPerSec,
> - This->mmdev_period_rt, 10000000);
> + stream->mmdev_period_frames = MulDiv(fmt->nSamplesPerSec,
> + stream->mmdev_period_rt, 10000000);
>
> /* Buffer 4 ALSA periods if large enough, else 4 mmdevapi periods */
> - This->alsa_bufsize_frames = This->mmdev_period_frames * 4;
> + stream->alsa_bufsize_frames = stream->mmdev_period_frames * 4;
> if(err < 0 || alsa_period_us < period / 10)
> - err = snd_pcm_hw_params_set_buffer_size_near(This->pcm_handle,
> - This->hw_params, &This->alsa_bufsize_frames);
> + err = snd_pcm_hw_params_set_buffer_size_near(stream->pcm_handle,
> + stream->hw_params, &stream->alsa_bufsize_frames);
> else{
> unsigned int periods = 4;
> - err = snd_pcm_hw_params_set_periods_near(This->pcm_handle, This->hw_params, &periods, NULL);
> + err = snd_pcm_hw_params_set_periods_near(stream->pcm_handle, stream->hw_params, &periods, NULL);
> }
> if(err < 0)
> WARN("Unable to set buffer size: %d (%s)\n", err, snd_strerror(err));
>
> - if((err = snd_pcm_hw_params(This->pcm_handle, This->hw_params)) < 0){
> + if((err = snd_pcm_hw_params(stream->pcm_handle, stream->hw_params)) < 0){
> WARN("Unable to set hw params: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_get_period_size(This->hw_params,
> - &This->alsa_period_frames, NULL)) < 0){
> + if((err = snd_pcm_hw_params_get_period_size(stream->hw_params,
> + &stream->alsa_period_frames, NULL)) < 0){
> WARN("Unable to get period size: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_get_buffer_size(This->hw_params,
> - &This->alsa_bufsize_frames)) < 0){
> + if((err = snd_pcm_hw_params_get_buffer_size(stream->hw_params,
> + &stream->alsa_bufsize_frames)) < 0){
> WARN("Unable to get buffer size: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> @@ -1087,34 +1073,34 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
> goto exit;
> }
>
> - if((err = snd_pcm_sw_params_current(This->pcm_handle, sw_params)) < 0){
> + if((err = snd_pcm_sw_params_current(stream->pcm_handle, sw_params)) < 0){
> WARN("Unable to get sw_params: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> }
>
> - if((err = snd_pcm_sw_params_set_start_threshold(This->pcm_handle,
> + if((err = snd_pcm_sw_params_set_start_threshold(stream->pcm_handle,
> sw_params, 1)) < 0){
> WARN("Unable set start threshold to 1: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> }
>
> - if((err = snd_pcm_sw_params_set_stop_threshold(This->pcm_handle,
> - sw_params, This->alsa_bufsize_frames)) < 0){
> + if((err = snd_pcm_sw_params_set_stop_threshold(stream->pcm_handle,
> + sw_params, stream->alsa_bufsize_frames)) < 0){
> WARN("Unable set stop threshold to %lu: %d (%s)\n",
> - This->alsa_bufsize_frames, err, snd_strerror(err));
> + stream->alsa_bufsize_frames, err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> }
>
> - if((err = snd_pcm_sw_params(This->pcm_handle, sw_params)) < 0){
> + if((err = snd_pcm_sw_params(stream->pcm_handle, sw_params)) < 0){
> WARN("Unable to set sw params: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> }
>
> - if((err = snd_pcm_prepare(This->pcm_handle)) < 0){
> + if((err = snd_pcm_prepare(stream->pcm_handle)) < 0){
> WARN("Unable to prepare device: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_ENDPOINT_CREATE_FAILED;
> goto exit;
> @@ -1125,42 +1111,42 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
> * or surprising rounding as seen with 22050x8x1 with Pulse:
> * ALSA period 220 vs. 221 frames in mmdevapi and
> * buffer 883 vs. 2205 frames in mmdevapi! */
> - This->bufsize_frames = MulDiv(duration, fmt->nSamplesPerSec, 10000000);
> + stream->bufsize_frames = MulDiv(duration, fmt->nSamplesPerSec, 10000000);
> if(mode == AUDCLNT_SHAREMODE_EXCLUSIVE)
> - This->bufsize_frames -= This->bufsize_frames % This->mmdev_period_frames;
> - This->hidden_frames = This->alsa_period_frames + This->mmdev_period_frames +
> + stream->bufsize_frames -= stream->bufsize_frames % stream->mmdev_period_frames;
> + stream->hidden_frames = stream->alsa_period_frames + stream->mmdev_period_frames +
> MulDiv(fmt->nSamplesPerSec, EXTRA_SAFE_RT, 10000000);
> /* leave no less than about 1.33ms or 256 bytes of data after a rewind */
> - This->safe_rewind_frames = max(256 / fmt->nBlockAlign, MulDiv(133, fmt->nSamplesPerSec, 100000));
> + stream->safe_rewind_frames = max(256 / fmt->nBlockAlign, MulDiv(133, fmt->nSamplesPerSec, 100000));
>
> /* Check if the ALSA buffer is so small that it will run out before
> * the next MMDevAPI period tick occurs. Allow a little wiggle room
> * with 120% of the period time. */
> - if(This->alsa_bufsize_frames < 1.2 * This->mmdev_period_frames)
> + if(stream->alsa_bufsize_frames < 1.2 * stream->mmdev_period_frames)
> FIXME("ALSA buffer time is too small. Expect underruns. (%lu < %u * 1.2)\n",
> - This->alsa_bufsize_frames, This->mmdev_period_frames);
> + stream->alsa_bufsize_frames, stream->mmdev_period_frames);
>
> - This->fmt = clone_format(fmt);
> - if(!This->fmt){
> + stream->fmt = clone_format(fmt);
> + if(!stream->fmt){
> hr = E_OUTOFMEMORY;
> goto exit;
> }
>
> - This->local_buffer = HeapAlloc(GetProcessHeap(), 0,
> - This->bufsize_frames * fmt->nBlockAlign);
> - if(!This->local_buffer){
> + stream->local_buffer = HeapAlloc(GetProcessHeap(), 0,
> + stream->bufsize_frames * fmt->nBlockAlign);
> + if(!stream->local_buffer){
> hr = E_OUTOFMEMORY;
> goto exit;
> }
> - silence_buffer(This, This->local_buffer, This->bufsize_frames);
> + silence_buffer(stream, stream->local_buffer, stream->bufsize_frames);
>
> - This->silence_buf = HeapAlloc(GetProcessHeap(), 0,
> - This->alsa_period_frames * This->fmt->nBlockAlign);
> - if(!This->silence_buf){
> + stream->silence_buf = HeapAlloc(GetProcessHeap(), 0,
> + stream->alsa_period_frames * stream->fmt->nBlockAlign);
> + if(!stream->silence_buf){
> hr = E_OUTOFMEMORY;
> goto exit;
> }
> - silence_buffer(This, This->silence_buf, This->alsa_period_frames);
> + silence_buffer(stream, stream->silence_buf, stream->alsa_period_frames);
>
> This->channel_count = fmt->nChannels;
> This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float));
> @@ -1172,8 +1158,8 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
> for(i = 0; i < This->channel_count; ++i)
> This->vols[i] = 1.f;
>
> - This->share = mode;
> - This->flags = flags;
> + stream->share = mode;
> + stream->flags = flags;
>
> hr = get_audio_session(sessionguid, This->parent, This->channel_count,
> &This->session);
> @@ -1184,18 +1170,18 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>
> This->initted = TRUE;
>
> - TRACE("ALSA period: %lu frames\n", This->alsa_period_frames);
> - TRACE("ALSA buffer: %lu frames\n", This->alsa_bufsize_frames);
> - TRACE("MMDevice period: %u frames\n", This->mmdev_period_frames);
> - TRACE("MMDevice buffer: %u frames\n", This->bufsize_frames);
> + TRACE("ALSA period: %lu frames\n", stream->alsa_period_frames);
> + TRACE("ALSA buffer: %lu frames\n", stream->alsa_bufsize_frames);
> + TRACE("MMDevice period: %u frames\n", stream->mmdev_period_frames);
> + TRACE("MMDevice buffer: %u frames\n", stream->bufsize_frames);
>
> exit:
> HeapFree(GetProcessHeap(), 0, sw_params);
> if(FAILED(hr)){
> - HeapFree(GetProcessHeap(), 0, This->local_buffer);
> - This->local_buffer = NULL;
> - CoTaskMemFree(This->fmt);
> - This->fmt = NULL;
> + HeapFree(GetProcessHeap(), 0, stream->local_buffer);
> + stream->local_buffer = NULL;
> + CoTaskMemFree(stream->fmt);
> + stream->fmt = NULL;
> HeapFree(GetProcessHeap(), 0, This->vols);
> This->vols = NULL;
> }
> @@ -1210,6 +1196,7 @@ static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface,
> UINT32 *out)
> {
> ACImpl *This = impl_from_IAudioClient3(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)->(%p)\n", This, out);
>
> @@ -1223,7 +1210,7 @@ static HRESULT WINAPI AudioClient_GetBufferSize(IAudioClient3 *iface,
> return AUDCLNT_E_NOT_INITIALIZED;
> }
>
> - *out = This->bufsize_frames;
> + *out = stream->bufsize_frames;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -1234,6 +1221,7 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
> REFERENCE_TIME *latency)
> {
> ACImpl *This = impl_from_IAudioClient3(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)->(%p)\n", This, latency);
>
> @@ -1253,10 +1241,10 @@ static HRESULT WINAPI AudioClient_GetStreamLatency(IAudioClient3 *iface,
> * + EXTRA_SAFE (~4ms) to allow for late callback invocation / fluctuation;
> * + alsa_period such that ALSA always has at least one period to play. */
> if(This->dataflow == eRender)
> - *latency = MulDiv(This->hidden_frames, 10000000, This->fmt->nSamplesPerSec);
> + *latency = MulDiv(stream->hidden_frames, 10000000, stream->fmt->nSamplesPerSec);
> else
> - *latency = MulDiv(This->alsa_period_frames, 10000000, This->fmt->nSamplesPerSec)
> - + This->mmdev_period_rt;
> + *latency = MulDiv(stream->alsa_period_frames, 10000000, stream->fmt->nSamplesPerSec)
> + + stream->mmdev_period_rt;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -1267,6 +1255,7 @@ static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient3 *iface,
> UINT32 *out)
> {
> ACImpl *This = impl_from_IAudioClient3(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)->(%p)\n", This, out);
>
> @@ -1281,7 +1270,7 @@ static HRESULT WINAPI AudioClient_GetCurrentPadding(IAudioClient3 *iface,
> }
>
> /* padding is solely updated at callback time in shared mode */
> - *out = This->held_frames;
> + *out = stream->held_frames;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -1334,7 +1323,7 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface,
>
> EnterCriticalSection(&This->lock);
>
> - if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
> + if((err = snd_pcm_hw_params_any(This->stream->pcm_handle, This->stream->hw_params)) < 0){
> hr = AUDCLNT_E_DEVICE_INVALIDATED;
> goto exit;
> }
> @@ -1346,7 +1335,7 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface,
> goto exit;
> }
>
> - snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
> + snd_pcm_hw_params_get_format_mask(This->stream->hw_params, formats);
> format = alsa_format(fmt);
> if (format == SND_PCM_FORMAT_UNKNOWN ||
> !snd_pcm_format_mask_test(formats, format)){
> @@ -1360,13 +1349,13 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface,
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_get_rate_min(This->hw_params, &min, NULL)) < 0){
> + if((err = snd_pcm_hw_params_get_rate_min(This->stream->hw_params, &min, NULL)) < 0){
> hr = AUDCLNT_E_DEVICE_INVALIDATED;
> WARN("Unable to get min rate: %d (%s)\n", err, snd_strerror(err));
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max, NULL)) < 0){
> + if((err = snd_pcm_hw_params_get_rate_max(This->stream->hw_params, &max, NULL)) < 0){
> hr = AUDCLNT_E_DEVICE_INVALIDATED;
> WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
> goto exit;
> @@ -1377,13 +1366,13 @@ static HRESULT WINAPI AudioClient_IsFormatSupported(IAudioClient3 *iface,
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_get_channels_min(This->hw_params, &min)) < 0){
> + if((err = snd_pcm_hw_params_get_channels_min(This->stream->hw_params, &min)) < 0){
> hr = AUDCLNT_E_DEVICE_INVALIDATED;
> WARN("Unable to get min channels: %d (%s)\n", err, snd_strerror(err));
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_get_channels_max(This->hw_params, &max)) < 0){
> + if((err = snd_pcm_hw_params_get_channels_max(This->stream->hw_params, &max)) < 0){
> hr = AUDCLNT_E_DEVICE_INVALIDATED;
> WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
> goto exit;
> @@ -1469,13 +1458,13 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface,
>
> EnterCriticalSection(&This->lock);
>
> - if((err = snd_pcm_hw_params_any(This->pcm_handle, This->hw_params)) < 0){
> + if((err = snd_pcm_hw_params_any(This->stream->pcm_handle, This->stream->hw_params)) < 0){
> WARN("Unable to get hw_params: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_DEVICE_INVALIDATED;
> goto exit;
> }
>
> - snd_pcm_hw_params_get_format_mask(This->hw_params, formats);
> + snd_pcm_hw_params_get_format_mask(This->stream->hw_params, formats);
>
> fmt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
> if(snd_pcm_format_mask_test(formats, SND_PCM_FORMAT_FLOAT_LE)){
> @@ -1499,7 +1488,7 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface,
> goto exit;
> }
>
> - if((err = snd_pcm_hw_params_get_channels_max(This->hw_params,
> + if((err = snd_pcm_hw_params_get_channels_max(This->stream->hw_params,
> &max_channels)) < 0){
> WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_DEVICE_INVALIDATED;
> @@ -1529,7 +1518,7 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface,
>
> fmt->dwChannelMask = get_channel_mask(fmt->Format.nChannels);
>
> - if((err = snd_pcm_hw_params_get_rate_max(This->hw_params, &max_rate,
> + if((err = snd_pcm_hw_params_get_rate_max(This->stream->hw_params, &max_rate,
> NULL)) < 0){
> WARN("Unable to get max rate: %d (%s)\n", err, snd_strerror(err));
> hr = AUDCLNT_E_DEVICE_INVALIDATED;
> @@ -1590,97 +1579,98 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface,
> return S_OK;
> }
>
> -static BYTE *remap_channels(ACImpl *This, BYTE *buf, snd_pcm_uframes_t frames)
> +static BYTE *remap_channels(struct alsa_stream *stream, BYTE *buf, snd_pcm_uframes_t frames)
> {
> snd_pcm_uframes_t i;
> UINT c;
> - UINT bytes_per_sample = This->fmt->wBitsPerSample / 8;
> + UINT bytes_per_sample = stream->fmt->wBitsPerSample / 8;
>
> - if(!This->need_remapping)
> + if(!stream->need_remapping)
> return buf;
>
> - if(!This->remapping_buf){
> - This->remapping_buf = HeapAlloc(GetProcessHeap(), 0,
> - bytes_per_sample * This->alsa_channels * frames);
> - This->remapping_buf_frames = frames;
> - }else if(This->remapping_buf_frames < frames){
> - This->remapping_buf = HeapReAlloc(GetProcessHeap(), 0, This->remapping_buf,
> - bytes_per_sample * This->alsa_channels * frames);
> - This->remapping_buf_frames = frames;
> + if(!stream->remapping_buf){
> + stream->remapping_buf = HeapAlloc(GetProcessHeap(), 0,
> + bytes_per_sample * stream->alsa_channels * frames);
> + stream->remapping_buf_frames = frames;
> + }else if(stream->remapping_buf_frames < frames){
> + stream->remapping_buf = HeapReAlloc(GetProcessHeap(), 0, stream->remapping_buf,
> + bytes_per_sample * stream->alsa_channels * frames);
> + stream->remapping_buf_frames = frames;
> }
>
> - snd_pcm_format_set_silence(This->alsa_format, This->remapping_buf,
> - frames * This->alsa_channels);
> + snd_pcm_format_set_silence(stream->alsa_format, stream->remapping_buf,
> + frames * stream->alsa_channels);
>
> - switch(This->fmt->wBitsPerSample){
> + switch(stream->fmt->wBitsPerSample){
> case 8: {
> UINT8 *tgt_buf, *src_buf;
> - tgt_buf = This->remapping_buf;
> + tgt_buf = stream->remapping_buf;
> src_buf = buf;
> for(i = 0; i < frames; ++i){
> - for(c = 0; c < This->fmt->nChannels; ++c)
> - tgt_buf[This->alsa_channel_map[c]] = src_buf[c];
> - tgt_buf += This->alsa_channels;
> - src_buf += This->fmt->nChannels;
> + for(c = 0; c < stream->fmt->nChannels; ++c)
> + tgt_buf[stream->alsa_channel_map[c]] = src_buf[c];
> + tgt_buf += stream->alsa_channels;
> + src_buf += stream->fmt->nChannels;
> }
> break;
> }
> case 16: {
> UINT16 *tgt_buf, *src_buf;
> - tgt_buf = (UINT16*)This->remapping_buf;
> + tgt_buf = (UINT16*)stream->remapping_buf;
> src_buf = (UINT16*)buf;
> for(i = 0; i < frames; ++i){
> - for(c = 0; c < This->fmt->nChannels; ++c)
> - tgt_buf[This->alsa_channel_map[c]] = src_buf[c];
> - tgt_buf += This->alsa_channels;
> - src_buf += This->fmt->nChannels;
> + for(c = 0; c < stream->fmt->nChannels; ++c)
> + tgt_buf[stream->alsa_channel_map[c]] = src_buf[c];
> + tgt_buf += stream->alsa_channels;
> + src_buf += stream->fmt->nChannels;
> }
> }
> break;
> case 32: {
> UINT32 *tgt_buf, *src_buf;
> - tgt_buf = (UINT32*)This->remapping_buf;
> + tgt_buf = (UINT32*)stream->remapping_buf;
> src_buf = (UINT32*)buf;
> for(i = 0; i < frames; ++i){
> - for(c = 0; c < This->fmt->nChannels; ++c)
> - tgt_buf[This->alsa_channel_map[c]] = src_buf[c];
> - tgt_buf += This->alsa_channels;
> - src_buf += This->fmt->nChannels;
> + for(c = 0; c < stream->fmt->nChannels; ++c)
> + tgt_buf[stream->alsa_channel_map[c]] = src_buf[c];
> + tgt_buf += stream->alsa_channels;
> + src_buf += stream->fmt->nChannels;
> }
> }
> break;
> default: {
> BYTE *tgt_buf, *src_buf;
> - tgt_buf = This->remapping_buf;
> + tgt_buf = stream->remapping_buf;
> src_buf = buf;
> for(i = 0; i < frames; ++i){
> - for(c = 0; c < This->fmt->nChannels; ++c)
> - memcpy(&tgt_buf[This->alsa_channel_map[c] * bytes_per_sample],
> + for(c = 0; c < stream->fmt->nChannels; ++c)
> + memcpy(&tgt_buf[stream->alsa_channel_map[c] * bytes_per_sample],
> &src_buf[c * bytes_per_sample], bytes_per_sample);
> - tgt_buf += This->alsa_channels * bytes_per_sample;
> - src_buf += This->fmt->nChannels * bytes_per_sample;
> + tgt_buf += stream->alsa_channels * bytes_per_sample;
> + src_buf += stream->fmt->nChannels * bytes_per_sample;
> }
> }
> break;
> }
>
> - return This->remapping_buf;
> + return stream->remapping_buf;
> }
>
> static void adjust_buffer_volume(const ACImpl *This, BYTE *buf, snd_pcm_uframes_t frames, BOOL mute)
> {
> - float vol[ARRAY_SIZE(This->alsa_channel_map)];
> + struct alsa_stream *stream = This->stream;
> + float vol[ARRAY_SIZE(stream->alsa_channel_map)];
> BOOL adjust = FALSE;
> UINT32 i, channels;
> BYTE *end;
>
> - if (This->vol_adjusted_frames >= frames)
> + if (stream->vol_adjusted_frames >= frames)
> return;
> - channels = This->fmt->nChannels;
> + channels = stream->fmt->nChannels;
>
> if (mute)
> {
> - int err = snd_pcm_format_set_silence(This->alsa_format, buf, frames * channels);
> + int err = snd_pcm_format_set_silence(stream->alsa_format, buf, frames * channels);
> if (err < 0)
> WARN("Setting buffer to silence failed: %d (%s)\n", err, snd_strerror(err));
> return;
> @@ -1698,10 +1688,10 @@ static void adjust_buffer_volume(const ACImpl *This, BYTE *buf, snd_pcm_uframes_
> if (!adjust) return;
>
> /* Skip the frames we've already adjusted before */
> - end = buf + frames * This->fmt->nBlockAlign;
> - buf += This->vol_adjusted_frames * This->fmt->nBlockAlign;
> + end = buf + frames * stream->fmt->nBlockAlign;
> + buf += stream->vol_adjusted_frames * stream->fmt->nBlockAlign;
>
> - switch (This->alsa_format)
> + switch (stream->alsa_format)
> {
> #ifndef WORDS_BIGENDIAN
> #define PROCESS_BUFFER(type) do \
> @@ -1735,7 +1725,7 @@ static void adjust_buffer_volume(const ACImpl *This, BYTE *buf, snd_pcm_uframes_
> BYTE *p;
>
> /* After we adjust the volume, we need to mask out low bits */
> - if (This->alsa_format == SND_PCM_FORMAT_S20_3LE)
> + if (stream->alsa_format == SND_PCM_FORMAT_S20_3LE)
> mask = ~0x0fff;
>
> i = 0;
> @@ -1781,7 +1771,7 @@ static void adjust_buffer_volume(const ACImpl *This, BYTE *buf, snd_pcm_uframes_
> break;
> }
> default:
> - TRACE("Unhandled format %i, not adjusting volume.\n", This->alsa_format);
> + TRACE("Unhandled format %i, not adjusting volume.\n", stream->alsa_format);
> break;
> }
> }
> @@ -1789,17 +1779,18 @@ static void adjust_buffer_volume(const ACImpl *This, BYTE *buf, snd_pcm_uframes_
> static snd_pcm_sframes_t alsa_write_best_effort(ACImpl *This, BYTE *buf,
> snd_pcm_uframes_t frames, BOOL mute)
> {
> + struct alsa_stream *stream = This->stream;
> snd_pcm_sframes_t written;
>
> adjust_buffer_volume(This, buf, frames, mute);
>
> /* Mark the frames we've already adjusted */
> - if (This->vol_adjusted_frames < frames)
> - This->vol_adjusted_frames = frames;
> + if (stream->vol_adjusted_frames < frames)
> + stream->vol_adjusted_frames = frames;
>
> - buf = remap_channels(This, buf, frames);
> + buf = remap_channels(stream, buf, frames);
>
> - written = snd_pcm_writei(This->pcm_handle, buf, frames);
> + written = snd_pcm_writei(stream->pcm_handle, buf, frames);
> if(written < 0){
> int ret;
>
> @@ -1810,17 +1801,17 @@ static snd_pcm_sframes_t alsa_write_best_effort(ACImpl *This, BYTE *buf,
> WARN("writei failed, recovering: %ld (%s)\n", written,
> snd_strerror(written));
>
> - ret = snd_pcm_recover(This->pcm_handle, written, 0);
> + ret = snd_pcm_recover(stream->pcm_handle, written, 0);
> if(ret < 0){
> WARN("Could not recover: %d (%s)\n", ret, snd_strerror(ret));
> return ret;
> }
>
> - written = snd_pcm_writei(This->pcm_handle, buf, frames);
> + written = snd_pcm_writei(stream->pcm_handle, buf, frames);
> }
>
> if (written > 0)
> - This->vol_adjusted_frames -= written;
> + stream->vol_adjusted_frames -= written;
> return written;
> }
>
> @@ -1828,6 +1819,7 @@ static snd_pcm_sframes_t alsa_write_buffer_wrap(ACImpl *This, BYTE *buf,
> snd_pcm_uframes_t buflen, snd_pcm_uframes_t offs,
> snd_pcm_uframes_t to_write)
> {
> + struct alsa_stream *stream = This->stream;
> snd_pcm_sframes_t ret = 0;
>
> while(to_write){
> @@ -1839,7 +1831,7 @@ static snd_pcm_sframes_t alsa_write_buffer_wrap(ACImpl *This, BYTE *buf,
> else
> chunk = to_write;
>
> - tmp = alsa_write_best_effort(This, buf + offs * This->fmt->nBlockAlign, chunk, This->session->mute);
> + tmp = alsa_write_best_effort(This, buf + offs * stream->fmt->nBlockAlign, chunk, This->session->mute);
> if(tmp < 0)
> return ret;
> if(!tmp)
> @@ -1863,13 +1855,14 @@ static UINT buf_ptr_diff(UINT left, UINT right, UINT bufsize)
>
> static UINT data_not_in_alsa(ACImpl *This)
> {
> + struct alsa_stream *stream = This->stream;
> UINT32 diff;
>
> - diff = buf_ptr_diff(This->lcl_offs_frames, This->wri_offs_frames, This->bufsize_frames);
> + diff = buf_ptr_diff(stream->lcl_offs_frames, stream->wri_offs_frames, stream->bufsize_frames);
> if(diff)
> return diff;
>
> - return This->held_frames - This->data_in_alsa_frames;
> + return stream->held_frames - stream->data_in_alsa_frames;
> }
> /* Here's the buffer setup:
> *
> @@ -1891,25 +1884,26 @@ static UINT data_not_in_alsa(ACImpl *This)
> */
> static void alsa_write_data(ACImpl *This)
> {
> + struct alsa_stream *stream = This->stream;
> snd_pcm_sframes_t written;
> snd_pcm_uframes_t avail, max_copy_frames, data_frames_played;
> int err;
>
> /* this call seems to be required to get an accurate snd_pcm_state() */
> - avail = snd_pcm_avail_update(This->pcm_handle);
> + avail = snd_pcm_avail_update(stream->pcm_handle);
>
> - if(snd_pcm_state(This->pcm_handle) == SND_PCM_STATE_XRUN){
> + if(snd_pcm_state(stream->pcm_handle) == SND_PCM_STATE_XRUN){
> TRACE("XRun state, recovering\n");
>
> - avail = This->alsa_bufsize_frames;
> + avail = stream->alsa_bufsize_frames;
>
> - if((err = snd_pcm_recover(This->pcm_handle, -EPIPE, 1)) < 0)
> + if((err = snd_pcm_recover(stream->pcm_handle, -EPIPE, 1)) < 0)
> WARN("snd_pcm_recover failed: %d (%s)\n", err, snd_strerror(err));
>
> - if((err = snd_pcm_reset(This->pcm_handle)) < 0)
> + if((err = snd_pcm_reset(stream->pcm_handle)) < 0)
> WARN("snd_pcm_reset failed: %d (%s)\n", err, snd_strerror(err));
>
> - if((err = snd_pcm_prepare(This->pcm_handle)) < 0)
> + if((err = snd_pcm_prepare(stream->pcm_handle)) < 0)
> WARN("snd_pcm_prepare failed: %d (%s)\n", err, snd_strerror(err));
> }
>
> @@ -1917,61 +1911,63 @@ static void alsa_write_data(ACImpl *This)
>
> /* Add a lead-in when starting with too few frames to ensure
> * continuous rendering. Additional benefit: Force ALSA to start. */
> - if(This->data_in_alsa_frames == 0 && This->held_frames < This->alsa_period_frames)
> + if(stream->data_in_alsa_frames == 0 && stream->held_frames < stream->alsa_period_frames)
> {
> - alsa_write_best_effort(This, This->silence_buf, This->alsa_period_frames - This->held_frames, FALSE);
> - This->vol_adjusted_frames = 0;
> + alsa_write_best_effort(This, stream->silence_buf,
> + stream->alsa_period_frames - stream->held_frames, FALSE);
> + stream->vol_adjusted_frames = 0;
> }
>
> - if(This->started)
> + if(stream->started)
> max_copy_frames = data_not_in_alsa(This);
> else
> max_copy_frames = 0;
>
> - data_frames_played = min(This->data_in_alsa_frames, avail);
> - This->data_in_alsa_frames -= data_frames_played;
> + data_frames_played = min(stream->data_in_alsa_frames, avail);
> + stream->data_in_alsa_frames -= data_frames_played;
>
> - if(This->held_frames > data_frames_played){
> - if(This->started)
> - This->held_frames -= data_frames_played;
> + if(stream->held_frames > data_frames_played){
> + if(stream->started)
> + stream->held_frames -= data_frames_played;
> }else
> - This->held_frames = 0;
> + stream->held_frames = 0;
>
> while(avail && max_copy_frames){
> snd_pcm_uframes_t to_write;
>
> to_write = min(avail, max_copy_frames);
>
> - written = alsa_write_buffer_wrap(This, This->local_buffer,
> - This->bufsize_frames, This->lcl_offs_frames, to_write);
> + written = alsa_write_buffer_wrap(This, stream->local_buffer,
> + stream->bufsize_frames, stream->lcl_offs_frames, to_write);
> if(written <= 0)
> break;
>
> avail -= written;
> - This->lcl_offs_frames += written;
> - This->lcl_offs_frames %= This->bufsize_frames;
> - This->data_in_alsa_frames += written;
> + stream->lcl_offs_frames += written;
> + stream->lcl_offs_frames %= stream->bufsize_frames;
> + stream->data_in_alsa_frames += written;
> max_copy_frames -= written;
> }
>
> - if(This->event)
> - SetEvent(This->event);
> + if(stream->event)
> + SetEvent(stream->event);
> }
>
> static void alsa_read_data(ACImpl *This)
> {
> + struct alsa_stream *stream = This->stream;
> snd_pcm_sframes_t nread;
> - UINT32 pos = This->wri_offs_frames, limit = This->held_frames;
> + UINT32 pos = stream->wri_offs_frames, limit = stream->held_frames;
>
> - if(!This->started)
> + if(!stream->started)
> goto exit;
>
> /* FIXME: Detect overrun and signal DATA_DISCONTINUITY
> * How to count overrun frames and report them as position increase? */
> - limit = This->bufsize_frames - max(limit, pos);
> + limit = stream->bufsize_frames - max(limit, pos);
>
> - nread = snd_pcm_readi(This->pcm_handle,
> - This->local_buffer + pos * This->fmt->nBlockAlign, limit);
> + nread = snd_pcm_readi(stream->pcm_handle,
> + stream->local_buffer + pos * stream->fmt->nBlockAlign, limit);
> TRACE("read %ld from %u limit %u\n", nread, pos, limit);
> if(nread < 0){
> int ret;
> @@ -1981,14 +1977,14 @@ static void alsa_read_data(ACImpl *This)
>
> WARN("read failed, recovering: %ld (%s)\n", nread, snd_strerror(nread));
>
> - ret = snd_pcm_recover(This->pcm_handle, nread, 0);
> + ret = snd_pcm_recover(stream->pcm_handle, nread, 0);
> if(ret < 0){
> WARN("Recover failed: %d (%s)\n", ret, snd_strerror(ret));
> return;
> }
>
> - nread = snd_pcm_readi(This->pcm_handle,
> - This->local_buffer + pos * This->fmt->nBlockAlign, limit);
> + nread = snd_pcm_readi(stream->pcm_handle,
> + stream->local_buffer + pos * stream->fmt->nBlockAlign, limit);
> if(nread < 0){
> WARN("read failed: %ld (%s)\n", nread, snd_strerror(nread));
> return;
> @@ -1997,29 +1993,30 @@ static void alsa_read_data(ACImpl *This)
>
> if(This->session->mute){
> int err;
> - if((err = snd_pcm_format_set_silence(This->alsa_format,
> - This->local_buffer + pos * This->fmt->nBlockAlign,
> + if((err = snd_pcm_format_set_silence(stream->alsa_format,
> + stream->local_buffer + pos * stream->fmt->nBlockAlign,
> nread)) < 0)
> WARN("Setting buffer to silence failed: %d (%s)\n", err,
> snd_strerror(err));
> }
>
> - This->wri_offs_frames += nread;
> - This->wri_offs_frames %= This->bufsize_frames;
> - This->held_frames += nread;
> + stream->wri_offs_frames += nread;
> + stream->wri_offs_frames %= stream->bufsize_frames;
> + stream->held_frames += nread;
>
> exit:
> - if(This->event)
> - SetEvent(This->event);
> + if(stream->event)
> + SetEvent(stream->event);
> }
>
> static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
> {
> ACImpl *This = user;
> + struct alsa_stream *stream = This->stream;
>
> EnterCriticalSection(&This->lock);
>
> - QueryPerformanceCounter(&This->last_period_time);
> + QueryPerformanceCounter(&stream->last_period_time);
>
> if(This->dataflow == eRender)
> alsa_write_data(This);
> @@ -2029,17 +2026,18 @@ static void CALLBACK alsa_push_buffer_data(void *user, BOOLEAN timer)
> LeaveCriticalSection(&This->lock);
> }
>
> -static snd_pcm_uframes_t interp_elapsed_frames(ACImpl *This)
> +static snd_pcm_uframes_t interp_elapsed_frames(struct alsa_stream *stream)
> {
> LARGE_INTEGER time_freq, current_time, time_diff;
> QueryPerformanceFrequency(&time_freq);
> QueryPerformanceCounter(¤t_time);
> - time_diff.QuadPart = current_time.QuadPart - This->last_period_time.QuadPart;
> - return MulDiv(time_diff.QuadPart, This->fmt->nSamplesPerSec, time_freq.QuadPart);
> + 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(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
> @@ -2047,25 +2045,25 @@ static int alsa_rewind_best_effort(ACImpl *This)
> * buffer, minus 1.33ms for safety. */
>
> /* amount of data to leave in ALSA buffer */
> - leave = interp_elapsed_frames(This) + This->safe_rewind_frames;
> + leave = interp_elapsed_frames(stream) + stream->safe_rewind_frames;
>
> - if(This->held_frames < leave)
> - This->held_frames = 0;
> + if(stream->held_frames < leave)
> + stream->held_frames = 0;
> else
> - This->held_frames -= leave;
> + stream->held_frames -= leave;
>
> - if(This->data_in_alsa_frames < leave)
> + if(stream->data_in_alsa_frames < leave)
> len = 0;
> else
> - len = This->data_in_alsa_frames - leave;
> + len = stream->data_in_alsa_frames - leave;
>
> - TRACE("rewinding %lu frames, now held %u\n", len, This->held_frames);
> + 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(This->pcm_handle, len);
> + snd_pcm_rewind(stream->pcm_handle, len);
>
> - This->data_in_alsa_frames = 0;
> + stream->data_in_alsa_frames = 0;
>
> return len;
> }
> @@ -2073,6 +2071,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;
>
> TRACE("(%p)\n", This);
>
> @@ -2083,55 +2082,55 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient3 *iface)
> return AUDCLNT_E_NOT_INITIALIZED;
> }
>
> - if((This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !This->event){
> + if((stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) && !stream->event){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_EVENTHANDLE_NOT_SET;
> }
>
> - if(This->started){
> + if(stream->started){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_NOT_STOPPED;
> }
>
> if(This->dataflow == eCapture){
> /* dump any data that might be leftover in the ALSA capture buffer */
> - snd_pcm_readi(This->pcm_handle, This->local_buffer,
> - This->bufsize_frames);
> + 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(This->pcm_handle);
> - avail = min(avail, This->held_frames);
> + avail = snd_pcm_avail_update(stream->pcm_handle);
> + avail = min(avail, stream->held_frames);
>
> - if(This->wri_offs_frames < This->held_frames)
> - offs = This->bufsize_frames - This->held_frames + This->wri_offs_frames;
> + if(stream->wri_offs_frames < stream->held_frames)
> + offs = stream->bufsize_frames - stream->held_frames + stream->wri_offs_frames;
> else
> - offs = This->wri_offs_frames - This->held_frames;
> + offs = stream->wri_offs_frames - stream->held_frames;
>
> /* fill it with data */
> - written = alsa_write_buffer_wrap(This, This->local_buffer,
> - This->bufsize_frames, offs, avail);
> + written = alsa_write_buffer_wrap(This, stream->local_buffer,
> + stream->bufsize_frames, offs, avail);
>
> if(written > 0){
> - This->lcl_offs_frames = (offs + written) % This->bufsize_frames;
> - This->data_in_alsa_frames = written;
> + stream->lcl_offs_frames = (offs + written) % stream->bufsize_frames;
> + stream->data_in_alsa_frames = written;
> }else{
> - This->lcl_offs_frames = offs;
> - This->data_in_alsa_frames = 0;
> + stream->lcl_offs_frames = offs;
> + stream->data_in_alsa_frames = 0;
> }
> }
>
> if(!This->timer){
> if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
> - This, 0, This->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){
> + This, 0, stream->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){
> LeaveCriticalSection(&This->lock);
> WARN("Unable to create timer: %u\n", GetLastError());
> return E_OUTOFMEMORY;
> }
> }
>
> - This->started = TRUE;
> + stream->started = TRUE;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -2141,6 +2140,7 @@ 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;
>
> TRACE("(%p)\n", This);
>
> @@ -2151,7 +2151,7 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
> return AUDCLNT_E_NOT_INITIALIZED;
> }
>
> - if(!This->started){
> + if(!stream->started){
> LeaveCriticalSection(&This->lock);
> return S_FALSE;
> }
> @@ -2159,7 +2159,7 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
> if(This->dataflow == eRender)
> alsa_rewind_best_effort(This);
>
> - This->started = FALSE;
> + stream->started = FALSE;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -2169,6 +2169,7 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient3 *iface)
> static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
> {
> ACImpl *This = impl_from_IAudioClient3(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)\n", This);
>
> @@ -2179,34 +2180,34 @@ static HRESULT WINAPI AudioClient_Reset(IAudioClient3 *iface)
> return AUDCLNT_E_NOT_INITIALIZED;
> }
>
> - if(This->started){
> + if(stream->started){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_NOT_STOPPED;
> }
>
> - if(This->getbuf_last){
> + if(stream->getbuf_last){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_BUFFER_OPERATION_PENDING;
> }
>
> - if(snd_pcm_drop(This->pcm_handle) < 0)
> + if(snd_pcm_drop(stream->pcm_handle) < 0)
> WARN("snd_pcm_drop failed\n");
>
> - if(snd_pcm_reset(This->pcm_handle) < 0)
> + if(snd_pcm_reset(stream->pcm_handle) < 0)
> WARN("snd_pcm_reset failed\n");
>
> - if(snd_pcm_prepare(This->pcm_handle) < 0)
> + if(snd_pcm_prepare(stream->pcm_handle) < 0)
> WARN("snd_pcm_prepare failed\n");
>
> if(This->dataflow == eRender){
> - This->written_frames = 0;
> - This->last_pos_frames = 0;
> + stream->written_frames = 0;
> + stream->last_pos_frames = 0;
> }else{
> - This->written_frames += This->held_frames;
> + stream->written_frames += stream->held_frames;
> }
> - This->held_frames = 0;
> - This->lcl_offs_frames = 0;
> - This->wri_offs_frames = 0;
> + stream->held_frames = 0;
> + stream->lcl_offs_frames = 0;
> + stream->wri_offs_frames = 0;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -2217,6 +2218,7 @@ static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
> HANDLE event)
> {
> ACImpl *This = impl_from_IAudioClient3(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)->(%p)\n", This, event);
>
> @@ -2230,18 +2232,18 @@ static HRESULT WINAPI AudioClient_SetEventHandle(IAudioClient3 *iface,
> return AUDCLNT_E_NOT_INITIALIZED;
> }
>
> - if(!(This->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
> + if(!(stream->flags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK)){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED;
> }
>
> - if (This->event){
> + if (stream->event){
> LeaveCriticalSection(&This->lock);
> FIXME("called twice\n");
> return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
> }
>
> - This->event = event;
> + stream->event = event;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -2489,6 +2491,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
> UINT32 frames, BYTE **data)
> {
> ACImpl *This = impl_from_IAudioRenderClient(iface);
> + struct alsa_stream *stream = This->stream;
> UINT32 write_pos;
>
> TRACE("(%p)->(%u, %p)\n", This, frames, data);
> @@ -2499,7 +2502,7 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
>
> EnterCriticalSection(&This->lock);
>
> - if(This->getbuf_last){
> + if(stream->getbuf_last){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_OUT_OF_ORDER;
> }
> @@ -2510,50 +2513,50 @@ static HRESULT WINAPI AudioRenderClient_GetBuffer(IAudioRenderClient *iface,
> }
>
> /* held_frames == GetCurrentPadding_nolock(); */
> - if(This->held_frames + frames > This->bufsize_frames){
> + if(stream->held_frames + frames > stream->bufsize_frames){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_BUFFER_TOO_LARGE;
> }
>
> - write_pos = This->wri_offs_frames;
> - if(write_pos + frames > This->bufsize_frames){
> - if(This->tmp_buffer_frames < frames){
> - HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
> - This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
> - frames * This->fmt->nBlockAlign);
> - if(!This->tmp_buffer){
> + write_pos = stream->wri_offs_frames;
> + if(write_pos + frames > stream->bufsize_frames){
> + if(stream->tmp_buffer_frames < frames){
> + HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
> + stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
> + frames * stream->fmt->nBlockAlign);
> + if(!stream->tmp_buffer){
> LeaveCriticalSection(&This->lock);
> return E_OUTOFMEMORY;
> }
> - This->tmp_buffer_frames = frames;
> + stream->tmp_buffer_frames = frames;
> }
> - *data = This->tmp_buffer;
> - This->getbuf_last = -frames;
> + *data = stream->tmp_buffer;
> + stream->getbuf_last = -frames;
> }else{
> - *data = This->local_buffer + write_pos * This->fmt->nBlockAlign;
> - This->getbuf_last = frames;
> + *data = stream->local_buffer + write_pos * stream->fmt->nBlockAlign;
> + stream->getbuf_last = frames;
> }
>
> - silence_buffer(This, *data, frames);
> + silence_buffer(stream, *data, frames);
>
> LeaveCriticalSection(&This->lock);
>
> return S_OK;
> }
>
> -static void alsa_wrap_buffer(ACImpl *This, BYTE *buffer, UINT32 written_frames)
> +static void alsa_wrap_buffer(struct alsa_stream *stream, BYTE *buffer, UINT32 written_frames)
> {
> - snd_pcm_uframes_t write_offs_frames = This->wri_offs_frames;
> - UINT32 write_offs_bytes = write_offs_frames * This->fmt->nBlockAlign;
> - snd_pcm_uframes_t chunk_frames = This->bufsize_frames - write_offs_frames;
> - UINT32 chunk_bytes = chunk_frames * This->fmt->nBlockAlign;
> - UINT32 written_bytes = written_frames * This->fmt->nBlockAlign;
> + snd_pcm_uframes_t write_offs_frames = stream->wri_offs_frames;
> + UINT32 write_offs_bytes = write_offs_frames * stream->fmt->nBlockAlign;
> + snd_pcm_uframes_t chunk_frames = stream->bufsize_frames - write_offs_frames;
> + UINT32 chunk_bytes = chunk_frames * stream->fmt->nBlockAlign;
> + UINT32 written_bytes = written_frames * stream->fmt->nBlockAlign;
>
> if(written_bytes <= chunk_bytes){
> - memcpy(This->local_buffer + write_offs_bytes, buffer, written_bytes);
> + memcpy(stream->local_buffer + write_offs_bytes, buffer, written_bytes);
> }else{
> - memcpy(This->local_buffer + write_offs_bytes, buffer, chunk_bytes);
> - memcpy(This->local_buffer, buffer + chunk_bytes,
> + memcpy(stream->local_buffer + write_offs_bytes, buffer, chunk_bytes);
> + memcpy(stream->local_buffer, buffer + chunk_bytes,
> written_bytes - chunk_bytes);
> }
> }
> @@ -2562,6 +2565,7 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
> IAudioRenderClient *iface, UINT32 written_frames, DWORD flags)
> {
> ACImpl *This = impl_from_IAudioRenderClient(iface);
> + struct alsa_stream *stream = This->stream;
> BYTE *buffer;
>
> TRACE("(%p)->(%u, %x)\n", This, written_frames, flags);
> @@ -2569,37 +2573,37 @@ static HRESULT WINAPI AudioRenderClient_ReleaseBuffer(
> EnterCriticalSection(&This->lock);
>
> if(!written_frames){
> - This->getbuf_last = 0;
> + stream->getbuf_last = 0;
> LeaveCriticalSection(&This->lock);
> return S_OK;
> }
>
> - if(!This->getbuf_last){
> + if(!stream->getbuf_last){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_OUT_OF_ORDER;
> }
>
> - if(written_frames > (This->getbuf_last >= 0 ? This->getbuf_last : -This->getbuf_last)){
> + if(written_frames > (stream->getbuf_last >= 0 ? stream->getbuf_last : -stream->getbuf_last)){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_INVALID_SIZE;
> }
>
> - if(This->getbuf_last >= 0)
> - buffer = This->local_buffer + This->wri_offs_frames * This->fmt->nBlockAlign;
> + if(stream->getbuf_last >= 0)
> + buffer = stream->local_buffer + stream->wri_offs_frames * stream->fmt->nBlockAlign;
> else
> - buffer = This->tmp_buffer;
> + buffer = stream->tmp_buffer;
>
> if(flags & AUDCLNT_BUFFERFLAGS_SILENT)
> - silence_buffer(This, buffer, written_frames);
> + silence_buffer(stream, buffer, written_frames);
>
> - if(This->getbuf_last < 0)
> - alsa_wrap_buffer(This, buffer, written_frames);
> + if(stream->getbuf_last < 0)
> + alsa_wrap_buffer(stream, buffer, written_frames);
>
> - This->wri_offs_frames += written_frames;
> - This->wri_offs_frames %= This->bufsize_frames;
> - This->held_frames += written_frames;
> - This->written_frames += written_frames;
> - This->getbuf_last = 0;
> + stream->wri_offs_frames += written_frames;
> + stream->wri_offs_frames %= stream->bufsize_frames;
> + stream->held_frames += written_frames;
> + stream->written_frames += written_frames;
> + stream->getbuf_last = 0;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -2656,6 +2660,7 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
> UINT64 *qpcpos)
> {
> ACImpl *This = impl_from_IAudioCaptureClient(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This, data, frames, flags,
> devpos, qpcpos);
> @@ -2670,49 +2675,49 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface,
>
> EnterCriticalSection(&This->lock);
>
> - if(This->getbuf_last){
> + if(stream->getbuf_last){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_OUT_OF_ORDER;
> }
>
> /* hr = GetNextPacketSize(iface, frames); */
> - if(This->held_frames < This->mmdev_period_frames){
> + if(stream->held_frames < stream->mmdev_period_frames){
> *frames = 0;
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_S_BUFFER_EMPTY;
> }
> - *frames = This->mmdev_period_frames;
> + *frames = stream->mmdev_period_frames;
>
> - if(This->lcl_offs_frames + *frames > This->bufsize_frames){
> + if(stream->lcl_offs_frames + *frames > stream->bufsize_frames){
> UINT32 chunk_bytes, offs_bytes, frames_bytes;
> - if(This->tmp_buffer_frames < *frames){
> - HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
> - This->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
> - *frames * This->fmt->nBlockAlign);
> - if(!This->tmp_buffer){
> + if(stream->tmp_buffer_frames < *frames){
> + HeapFree(GetProcessHeap(), 0, stream->tmp_buffer);
> + stream->tmp_buffer = HeapAlloc(GetProcessHeap(), 0,
> + *frames * stream->fmt->nBlockAlign);
> + if(!stream->tmp_buffer){
> LeaveCriticalSection(&This->lock);
> return E_OUTOFMEMORY;
> }
> - This->tmp_buffer_frames = *frames;
> + stream->tmp_buffer_frames = *frames;
> }
>
> - *data = This->tmp_buffer;
> - chunk_bytes = (This->bufsize_frames - This->lcl_offs_frames) *
> - This->fmt->nBlockAlign;
> - offs_bytes = This->lcl_offs_frames * This->fmt->nBlockAlign;
> - frames_bytes = *frames * This->fmt->nBlockAlign;
> - memcpy(This->tmp_buffer, This->local_buffer + offs_bytes, chunk_bytes);
> - memcpy(This->tmp_buffer + chunk_bytes, This->local_buffer,
> + *data = stream->tmp_buffer;
> + chunk_bytes = (stream->bufsize_frames - stream->lcl_offs_frames) *
> + stream->fmt->nBlockAlign;
> + offs_bytes = stream->lcl_offs_frames * stream->fmt->nBlockAlign;
> + frames_bytes = *frames * stream->fmt->nBlockAlign;
> + memcpy(stream->tmp_buffer, stream->local_buffer + offs_bytes, chunk_bytes);
> + memcpy(stream->tmp_buffer + chunk_bytes, stream->local_buffer,
> frames_bytes - chunk_bytes);
> }else
> - *data = This->local_buffer +
> - This->lcl_offs_frames * This->fmt->nBlockAlign;
> + *data = stream->local_buffer +
> + stream->lcl_offs_frames * stream->fmt->nBlockAlign;
>
> - This->getbuf_last = *frames;
> + stream->getbuf_last = *frames;
> *flags = 0;
>
> if(devpos)
> - *devpos = This->written_frames;
> + *devpos = stream->written_frames;
> if(qpcpos){ /* fixme: qpc of recording time */
> LARGE_INTEGER stamp, freq;
> QueryPerformanceCounter(&stamp);
> @@ -2729,32 +2734,33 @@ static HRESULT WINAPI AudioCaptureClient_ReleaseBuffer(
> IAudioCaptureClient *iface, UINT32 done)
> {
> ACImpl *This = impl_from_IAudioCaptureClient(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)->(%u)\n", This, done);
>
> EnterCriticalSection(&This->lock);
>
> if(!done){
> - This->getbuf_last = 0;
> + stream->getbuf_last = 0;
> LeaveCriticalSection(&This->lock);
> return S_OK;
> }
>
> - if(!This->getbuf_last){
> + if(!stream->getbuf_last){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_OUT_OF_ORDER;
> }
>
> - if(This->getbuf_last != done){
> + if(stream->getbuf_last != done){
> LeaveCriticalSection(&This->lock);
> return AUDCLNT_E_INVALID_SIZE;
> }
>
> - This->written_frames += done;
> - This->held_frames -= done;
> - This->lcl_offs_frames += done;
> - This->lcl_offs_frames %= This->bufsize_frames;
> - This->getbuf_last = 0;
> + stream->written_frames += done;
> + stream->held_frames -= done;
> + stream->lcl_offs_frames += done;
> + stream->lcl_offs_frames %= stream->bufsize_frames;
> + stream->getbuf_last = 0;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -2765,6 +2771,7 @@ static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
> IAudioCaptureClient *iface, UINT32 *frames)
> {
> ACImpl *This = impl_from_IAudioCaptureClient(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)->(%p)\n", This, frames);
>
> @@ -2773,7 +2780,7 @@ static HRESULT WINAPI AudioCaptureClient_GetNextPacketSize(
>
> EnterCriticalSection(&This->lock);
>
> - *frames = This->held_frames < This->mmdev_period_frames ? 0 : This->mmdev_period_frames;
> + *frames = stream->held_frames < stream->mmdev_period_frames ? 0 : stream->mmdev_period_frames;
>
> LeaveCriticalSection(&This->lock);
>
> @@ -2829,13 +2836,14 @@ static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
> static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
> {
> ACImpl *This = impl_from_IAudioClock(iface);
> + struct alsa_stream *stream = This->stream;
>
> TRACE("(%p)->(%p)\n", This, freq);
>
> - if(This->share == AUDCLNT_SHAREMODE_SHARED)
> - *freq = (UINT64)This->fmt->nSamplesPerSec * This->fmt->nBlockAlign;
> + if(stream->share == AUDCLNT_SHAREMODE_SHARED)
> + *freq = (UINT64)stream->fmt->nSamplesPerSec * stream->fmt->nBlockAlign;
> else
> - *freq = This->fmt->nSamplesPerSec;
> + *freq = stream->fmt->nSamplesPerSec;
>
> return S_OK;
> }
> @@ -2844,6 +2852,7 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
> UINT64 *qpctime)
> {
> ACImpl *This = impl_from_IAudioClock(iface);
> + struct alsa_stream *stream = This->stream;
> UINT64 position;
> snd_pcm_state_t alsa_state;
>
> @@ -2855,38 +2864,38 @@ static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
> EnterCriticalSection(&This->lock);
>
> /* avail_update required to get accurate snd_pcm_state() */
> - snd_pcm_avail_update(This->pcm_handle);
> - alsa_state = snd_pcm_state(This->pcm_handle);
> + snd_pcm_avail_update(stream->pcm_handle);
> + alsa_state = snd_pcm_state(stream->pcm_handle);
>
> if(This->dataflow == eRender){
> - position = This->written_frames - This->held_frames;
> + position = stream->written_frames - stream->held_frames;
>
> - if(This->started && alsa_state == SND_PCM_STATE_RUNNING && This->held_frames)
> + if(stream->started && alsa_state == SND_PCM_STATE_RUNNING && stream->held_frames)
> /* we should be using snd_pcm_delay here, but it is broken
> * especially during ALSA device underrun. instead, let's just
> * interpolate between periods with the system timer. */
> - position += interp_elapsed_frames(This);
> + position += interp_elapsed_frames(stream);
>
> - position = min(position, This->written_frames - This->held_frames + This->mmdev_period_frames);
> + position = min(position, stream->written_frames - stream->held_frames + stream->mmdev_period_frames);
>
> - position = min(position, This->written_frames);
> + position = min(position, stream->written_frames);
> }else
> - position = This->written_frames + This->held_frames;
> + position = stream->written_frames + stream->held_frames;
>
> /* ensure monotic growth */
> - if(position < This->last_pos_frames)
> - position = This->last_pos_frames;
> + if(position < stream->last_pos_frames)
> + position = stream->last_pos_frames;
> else
> - This->last_pos_frames = position;
> + stream->last_pos_frames = position;
>
> TRACE("frames written: %u, held: %u, state: 0x%x, position: %u\n",
> - (UINT32)(This->written_frames%1000000000), This->held_frames,
> + (UINT32)(stream->written_frames%1000000000), stream->held_frames,
> alsa_state, (UINT32)(position%1000000000));
>
> LeaveCriticalSection(&This->lock);
>
> - if(This->share == AUDCLNT_SHAREMODE_SHARED)
> - *pos = position * This->fmt->nBlockAlign;
> + if(stream->share == AUDCLNT_SHAREMODE_SHARED)
> + *pos = position * stream->fmt->nBlockAlign;
> else
> *pos = position;
>
> @@ -3056,7 +3065,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
>
> LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){
> EnterCriticalSection(&client->lock);
> - if(client->started){
> + if(client->stream->started){
> *state = AudioSessionStateActive;
> LeaveCriticalSection(&client->lock);
> LeaveCriticalSection(&g_sessions_lock);
> diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
> index f3014d0b448..8a20710b7e5 100644
> --- a/dlls/winealsa.drv/unixlib.h
> +++ b/dlls/winealsa.drv/unixlib.h
> @@ -16,6 +16,41 @@
> * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
> */
>
> +#include "audioclient.h"
> +
> +struct alsa_stream
> +{
> + snd_pcm_t *pcm_handle;
> + snd_pcm_uframes_t alsa_bufsize_frames, alsa_period_frames, safe_rewind_frames;
> + snd_pcm_hw_params_t *hw_params; /* does not hold state between calls */
> + snd_pcm_format_t alsa_format;
> +
> + LARGE_INTEGER last_period_time;
> +
> + WAVEFORMATEX *fmt;
> + DWORD flags;
> + AUDCLNT_SHAREMODE share;
> + HANDLE event;
> +
> + BOOL need_remapping;
> + int alsa_channels;
> + int alsa_channel_map[32];
> +
> + BOOL started;
> + REFERENCE_TIME mmdev_period_rt;
> + UINT64 written_frames, last_pos_frames;
> + UINT32 bufsize_frames, held_frames, tmp_buffer_frames, mmdev_period_frames;
> + snd_pcm_uframes_t remapping_buf_frames;
> + UINT32 lcl_offs_frames; /* offs into local_buffer where valid data starts */
> + UINT32 wri_offs_frames; /* where to write fresh data in local_buffer */
> + UINT32 hidden_frames; /* ALSA reserve to ensure continuous rendering */
> + UINT32 vol_adjusted_frames; /* Frames we've already adjusted the volume of but didn't write yet */
> + UINT32 data_in_alsa_frames;
> +
> + BYTE *local_buffer, *tmp_buffer, *remapping_buf, *silence_buf;
> + LONG32 getbuf_last; /* <0 when using tmp_buffer */
> +};
> +
> struct endpoint
> {
> WCHAR *name;
> --
> 2.25.1
>
>
More information about the wine-devel
mailing list