Wine-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 5 participants
- 84522 discussions
Signed-off-by: Huw Davies <huw(a)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
2
1
Mainly just for simplicity.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/mmdevdrv.c | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index abec9dc969a..0549752dc3f 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -77,8 +77,6 @@ typedef struct _AudioSession {
float *channel_vols;
BOOL mute;
- CRITICAL_SECTION lock;
-
struct list entry;
} AudioSession;
@@ -748,9 +746,6 @@ static AudioSession *create_session(const GUID *guid, IMMDevice *device,
list_add_head(&g_sessions, &ret->entry);
- InitializeCriticalSection(&ret->lock);
- ret->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": AudioSession.lock");
-
session_init_vols(ret, num_channels);
ret->master_vol = 1.f;
@@ -3283,11 +3278,11 @@ static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
TRACE("ALSA does not support volume control\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
session->master_vol = level;
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -3573,11 +3568,11 @@ static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
TRACE("ALSA does not support volume control\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
session->channel_vols[index] = level;
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
@@ -3623,12 +3618,12 @@ static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
TRACE("ALSA does not support volume control\n");
- EnterCriticalSection(&session->lock);
+ EnterCriticalSection(&g_sessions_lock);
for(i = 0; i < count; ++i)
session->channel_vols[i] = levels[i];
- LeaveCriticalSection(&session->lock);
+ LeaveCriticalSection(&g_sessions_lock);
return S_OK;
}
--
2.25.1
2
1
[PATCH 1/8] winealsa: Explicitly store the name and channel count in the audio client.
by Huw Davies 17 Feb '22
by Huw Davies 17 Feb '22
17 Feb '22
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/mmdevdrv.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index 516bba1e5fc..abec9dc969a 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -119,6 +119,7 @@ struct ACImpl {
AUDCLNT_SHAREMODE share;
HANDLE event;
float *vols;
+ UINT32 channel_count;
BOOL need_remapping;
int alsa_channels;
@@ -145,6 +146,9 @@ struct ACImpl {
AudioSessionWrapper *session_wrapper;
struct list entry;
+
+ /* Keep at end */
+ char alsa_name[1];
};
typedef struct _SessionMgr {
@@ -472,6 +476,7 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
char alsa_name[256];
EDataFlow dataflow;
HRESULT hr;
+ int len;
TRACE("%s %p %p\n", debugstr_guid(guid), dev, out);
@@ -481,7 +486,8 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
if(dataflow != eRender && dataflow != eCapture)
return E_UNEXPECTED;
- This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACImpl));
+ len = strlen(alsa_name);
+ This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, offsetof(ACImpl, alsa_name[len + 1]));
if(!This)
return E_OUTOFMEMORY;
@@ -499,6 +505,8 @@ 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);
if(err < 0){
HeapFree(GetProcessHeap(), 0, This);
@@ -1159,19 +1167,20 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
}
silence_buffer(This, This->silence_buf, This->alsa_period_frames);
- This->vols = HeapAlloc(GetProcessHeap(), 0, fmt->nChannels * sizeof(float));
+ This->channel_count = fmt->nChannels;
+ This->vols = HeapAlloc(GetProcessHeap(), 0, This->channel_count * sizeof(float));
if(!This->vols){
hr = E_OUTOFMEMORY;
goto exit;
}
- for(i = 0; i < fmt->nChannels; ++i)
+ for(i = 0; i < This->channel_count; ++i)
This->vols[i] = 1.f;
This->share = mode;
This->flags = flags;
- hr = get_audio_session(sessionguid, This->parent, fmt->nChannels,
+ hr = get_audio_session(sessionguid, This->parent, This->channel_count,
&This->session);
if(FAILED(hr))
goto exit;
@@ -3385,7 +3394,7 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelCount(
if(!out)
return E_POINTER;
- *out = This->fmt->nChannels;
+ *out = This->channel_count;
return S_OK;
}
@@ -3400,7 +3409,7 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
if(level < 0.f || level > 1.f)
return E_INVALIDARG;
- if(index >= This->fmt->nChannels)
+ if(index >= This->channel_count)
return E_INVALIDARG;
TRACE("ALSA does not support volume control\n");
@@ -3424,7 +3433,7 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
if(!level)
return E_POINTER;
- if(index >= This->fmt->nChannels)
+ if(index >= This->channel_count)
return E_INVALIDARG;
*level = This->vols[index];
@@ -3443,7 +3452,7 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
if(!levels)
return E_POINTER;
- if(count != This->fmt->nChannels)
+ if(count != This->channel_count)
return E_INVALIDARG;
TRACE("ALSA does not support volume control\n");
@@ -3469,7 +3478,7 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
if(!levels)
return E_POINTER;
- if(count != This->fmt->nChannels)
+ if(count != This->channel_count)
return E_INVALIDARG;
EnterCriticalSection(&This->lock);
--
2.25.1
2
1
[PATCH vkd3d v4 3/3] vkd3d-shader/hlsl: Cover all numeric types in constant folding operations.
by Matteo Bruni 17 Feb '22
by Matteo Bruni 17 Feb '22
17 Feb '22
From: Francisco Casas <fcasas(a)codeweavers.com>
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni(a)codeweavers.com>
---
Makefile.am | 1 -
libs/vkd3d-shader/hlsl_constant_ops.c | 331 ++++++++++++++++++--------
2 files changed, 232 insertions(+), 100 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 94fa522a..8617a09d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -96,7 +96,6 @@ vkd3d_shader_tests = \
tests/hlsl-vector-indexing.shader_test \
tests/hlsl-vector-indexing-uniform.shader_test \
tests/math.shader_test \
- tests/max.shader_test \
tests/pow.shader_test \
tests/preproc-if.shader_test \
tests/preproc-ifdef.shader_test \
diff --git a/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d-shader/hlsl_constant_ops.c
index 9e19cef4..51cee179 100644
--- a/libs/vkd3d-shader/hlsl_constant_ops.c
+++ b/libs/vkd3d-shader/hlsl_constant_ops.c
@@ -20,11 +20,216 @@
#include "hlsl.h"
+static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst, struct hlsl_ir_constant *src)
+{
+ unsigned int k;
+ uint32_t u;
+ int32_t i;
+ double d;
+ float f;
+ bool b;
+
+ if (dst->node.data_type->dimx != src->node.data_type->dimx
+ || dst->node.data_type->dimy != src->node.data_type->dimy)
+ {
+ FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, src->node.data_type),
+ debug_hlsl_type(ctx, dst->node.data_type));
+ return false;
+ }
+
+ for (k = 0; k < 4; ++k)
+ {
+ switch (src->node.data_type->base_type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ u = src->value[k].f;
+ i = src->value[k].f;
+ f = src->value[k].f;
+ d = src->value[k].f;
+ b = src->value[k].f;
+ break;
+
+ case HLSL_TYPE_DOUBLE:
+ u = src->value[k].d;
+ i = src->value[k].d;
+ f = src->value[k].d;
+ d = src->value[k].d;
+ b = src->value[k].d;
+ break;
+
+ case HLSL_TYPE_INT:
+ u = src->value[k].i;
+ i = src->value[k].i;
+ f = src->value[k].i;
+ d = src->value[k].i;
+ b = src->value[k].i;
+ break;
+
+ case HLSL_TYPE_UINT:
+ u = src->value[k].u;
+ i = src->value[k].u;
+ f = src->value[k].u;
+ d = src->value[k].u;
+ b = src->value[k].u;
+ break;
+
+ case HLSL_TYPE_BOOL:
+ u = src->value[k].b;
+ i = src->value[k].b;
+ f = src->value[k].b;
+ d = src->value[k].b;
+ b = src->value[k].b;
+ break;
+
+ default:
+ FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, src->node.data_type),
+ debug_hlsl_type(ctx, dst->node.data_type));
+ return false;
+ }
+
+ switch (dst->node.data_type->base_type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->value[k].f = f;
+ break;
+
+ case HLSL_TYPE_DOUBLE:
+ dst->value[k].d = d;
+ break;
+
+ case HLSL_TYPE_INT:
+ dst->value[k].i = i;
+ break;
+
+ case HLSL_TYPE_UINT:
+ dst->value[k].u = u;
+ break;
+
+ case HLSL_TYPE_BOOL:
+ dst->value[k].b = b;
+ break;
+
+ default:
+ FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, src->node.data_type),
+ debug_hlsl_type(ctx, dst->node.data_type));
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool fold_neg(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst, struct hlsl_ir_constant *src)
+{
+ enum hlsl_base_type type = dst->node.data_type->base_type;
+ unsigned int k;
+
+ assert(type == src->node.data_type->base_type);
+
+ for (k = 0; k < 4; ++k)
+ {
+ switch (type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->value[k].f = -src->value[k].f;
+ break;
+
+ case HLSL_TYPE_DOUBLE:
+ dst->value[k].d = -src->value[k].d;
+ break;
+
+ case HLSL_TYPE_INT:
+ case HLSL_TYPE_UINT:
+ dst->value[k].u = -src->value[k].u;
+ break;
+
+ default:
+ FIXME("Fold negation for type %s.\n", debug_hlsl_type(ctx, dst->node.data_type));
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool fold_add(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst, struct hlsl_ir_constant *src1,
+ struct hlsl_ir_constant *src2)
+{
+ enum hlsl_base_type type = dst->node.data_type->base_type;
+ unsigned int k;
+
+ assert(type == src1->node.data_type->base_type);
+ assert(type == src2->node.data_type->base_type);
+
+ for (k = 0; k < 4; ++k)
+ {
+ switch (type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->value[k].f = src1->value[k].f + src2->value[k].f;
+ break;
+
+ case HLSL_TYPE_DOUBLE:
+ dst->value[k].d = src1->value[k].d + src2->value[k].d;
+ break;
+
+ /* Handling HLSL_TYPE_INT through the unsigned field to avoid
+ * undefined behavior with signed integers in C. */
+ case HLSL_TYPE_INT:
+ case HLSL_TYPE_UINT:
+ dst->value[k].u = src1->value[k].u + src2->value[k].u;
+ break;
+
+ default:
+ FIXME("Fold addition for type %s.\n", debug_hlsl_type(ctx, dst->node.data_type));
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool fold_mul(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst,
+ struct hlsl_ir_constant *src1, struct hlsl_ir_constant *src2)
+{
+ enum hlsl_base_type type = dst->node.data_type->base_type;
+
+ assert(type == src1->node.data_type->base_type);
+ assert(type == src2->node.data_type->base_type);
+
+ for (int k = 0; k < 4; ++k)
+ {
+ switch (type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->value[k].f = src1->value[k].f * src2->value[k].f;
+ break;
+
+ case HLSL_TYPE_DOUBLE:
+ dst->value[k].d = src1->value[k].d * src2->value[k].d;
+ break;
+
+ case HLSL_TYPE_INT:
+ case HLSL_TYPE_UINT:
+ dst->value[k].u = src1->value[k].u * src2->value[k].u;
+ break;
+
+ default:
+ FIXME("Fold multiplication for type %s.\n", debug_hlsl_type(ctx, dst->node.data_type));
+ return false;
+ }
+ }
+ return true;
+}
+
bool hlsl_fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_ir_constant *arg1, *arg2 = NULL, *res;
struct hlsl_ir_expr *expr;
- unsigned int i, dimx;
+ unsigned int i;
+ bool success;
if (instr->type != HLSL_IR_EXPR)
return false;
@@ -38,115 +243,43 @@ bool hlsl_fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void
arg1 = hlsl_ir_constant(expr->operands[0].node);
if (expr->operands[1].node)
arg2 = hlsl_ir_constant(expr->operands[1].node);
- dimx = instr->data_type->dimx;
if (!(res = hlsl_alloc(ctx, sizeof(*res))))
return false;
init_node(&res->node, HLSL_IR_CONSTANT, instr->data_type, instr->loc);
- switch (instr->data_type->base_type)
+ switch (expr->op)
{
- case HLSL_TYPE_FLOAT:
- {
- switch (expr->op)
- {
- case HLSL_OP1_CAST:
- if (instr->data_type->dimx != arg1->node.data_type->dimx
- || instr->data_type->dimy != arg1->node.data_type->dimy)
- {
- FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, arg1->node.data_type),
- debug_hlsl_type(ctx, instr->data_type));
- vkd3d_free(res);
- return false;
- }
-
- switch (arg1->node.data_type->base_type)
- {
- case HLSL_TYPE_INT:
- for (i = 0; i < dimx; ++i)
- res->value[i].f = arg1->value[i].i;
- break;
-
- case HLSL_TYPE_UINT:
- for (i = 0; i < dimx; ++i)
- res->value[i].f = arg1->value[i].u;
- break;
-
- default:
- FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, arg1->node.data_type),
- debug_hlsl_type(ctx, instr->data_type));
- vkd3d_free(res);
- return false;
- }
- break;
-
- default:
- FIXME("Fold float op %#x.\n", expr->op);
- vkd3d_free(res);
- return false;
- }
+ case HLSL_OP1_CAST:
+ success = fold_cast(ctx, res, arg1);
break;
- }
- case HLSL_TYPE_UINT:
- {
- switch (expr->op)
- {
- case HLSL_OP1_CAST:
- if (instr->data_type->dimx != arg1->node.data_type->dimx
- || instr->data_type->dimy != arg1->node.data_type->dimy)
- {
- FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, arg1->node.data_type),
- debug_hlsl_type(ctx, instr->data_type));
- vkd3d_free(res);
- return false;
- }
-
- switch (arg1->node.data_type->base_type)
- {
- case HLSL_TYPE_INT:
- for (i = 0; i < dimx; ++i)
- res->value[i].i = arg1->value[i].u;
- break;
-
- default:
- FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, arg1->node.data_type),
- debug_hlsl_type(ctx, instr->data_type));
- vkd3d_free(res);
- return false;
- }
- break;
-
- case HLSL_OP1_NEG:
- for (i = 0; i < instr->data_type->dimx; ++i)
- res->value[i].u = -arg1->value[i].u;
- break;
-
- case HLSL_OP2_ADD:
- for (i = 0; i < instr->data_type->dimx; ++i)
- res->value[i].u = arg1->value[i].u + arg2->value[i].u;
- break;
-
- case HLSL_OP2_MUL:
- for (i = 0; i < instr->data_type->dimx; ++i)
- res->value[i].u = arg1->value[i].u * arg2->value[i].u;
- break;
-
- default:
- FIXME("Fold uint op %#x.\n", expr->op);
- vkd3d_free(res);
- return false;
- }
+ case HLSL_OP1_NEG:
+ success = fold_neg(ctx, res, arg1);
+ break;
+
+ case HLSL_OP2_ADD:
+ success = fold_add(ctx, res, arg1, arg2);
+ break;
+
+ case HLSL_OP2_MUL:
+ success = fold_mul(ctx, res, arg1, arg2);
break;
- }
default:
- FIXME("Fold type %#x op %#x.\n", instr->data_type->base_type, expr->op);
- vkd3d_free(res);
- return false;
+ FIXME("Fold \"%s\" expression.\n", debug_hlsl_expr_op(expr->op));
+ success = false;
+ break;
}
- list_add_before(&expr->node.entry, &res->node.entry);
- hlsl_replace_node(&expr->node, &res->node);
- return true;
+ if (success)
+ {
+ list_add_before(&expr->node.entry, &res->node.entry);
+ hlsl_replace_node(&expr->node, &res->node);
+ }
+ else
+ {
+ vkd3d_free(res);
+ }
+ return success;
}
--
2.34.1
3
2
[PATCH vkd3d v3 1/3] vkd3d-shader/hlsl: Move replace_node() to hlsl.c.
by Zebediah Figura 17 Feb '22
by Zebediah Figura 17 Feb '22
17 Feb '22
From: Francisco Casas <fcasas(a)codeweavers.com>
Also rename it to hlsl_replace_node().
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl.c | 14 ++++++++++++++
libs/vkd3d-shader/hlsl.h | 2 ++
libs/vkd3d-shader/hlsl_codegen.c | 25 ++++++-------------------
3 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 8a0f4b017..a9a427707 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -1400,6 +1400,20 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl
vkd3d_string_buffer_cleanup(&buffer);
}
+void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new)
+{
+ struct hlsl_src *src, *next;
+
+ LIST_FOR_EACH_ENTRY_SAFE(src, next, &old->uses, struct hlsl_src, entry)
+ {
+ hlsl_src_remove(src);
+ hlsl_src_from_node(src, new);
+ }
+ list_remove(&old->entry);
+ hlsl_free_instr(old);
+}
+
+
void hlsl_free_type(struct hlsl_type *type)
{
struct hlsl_struct_field *field, *next_field;
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index 3a69165e5..67fe1a8d5 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -713,6 +713,8 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl
int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
+void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
+
void hlsl_free_instr(struct hlsl_ir_node *node);
void hlsl_free_instr_list(struct list *list);
void hlsl_free_type(struct hlsl_type *type);
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index eac3513c9..77ddd979a 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -224,19 +224,6 @@ static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx
return progress;
}
-static void replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new)
-{
- struct hlsl_src *src, *next;
-
- LIST_FOR_EACH_ENTRY_SAFE(src, next, &old->uses, struct hlsl_src, entry)
- {
- hlsl_src_remove(src);
- hlsl_src_from_node(src, new);
- }
- list_remove(&old->entry);
- hlsl_free_instr(old);
-}
-
/* Lower casts from vec1 to vecN to swizzles. */
static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
@@ -267,7 +254,7 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, v
return false;
list_add_after(&new_cast->node.entry, &swizzle->node.entry);
- replace_node(&cast->node, &swizzle->node);
+ hlsl_replace_node(&cast->node, &swizzle->node);
return true;
}
@@ -437,7 +424,7 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx,
list_add_before(&node->entry, &swizzle_node->node.entry);
new_node = &swizzle_node->node;
}
- replace_node(node, new_node);
+ hlsl_replace_node(node, new_node);
return true;
}
@@ -566,7 +553,7 @@ static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst
if (hlsl_types_are_equal(src_type, dst_type)
|| (src_type->base_type == dst_type->base_type && is_vec1(src_type) && is_vec1(dst_type)))
{
- replace_node(&expr->node, expr->operands[0].node);
+ hlsl_replace_node(&expr->node, expr->operands[0].node);
return true;
}
}
@@ -708,7 +695,7 @@ static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins
return false;
list_add_after(&new_cast->node.entry, &swizzle->node.entry);
- replace_node(&cast->node, &swizzle->node);
+ hlsl_replace_node(&cast->node, &swizzle->node);
return true;
}
@@ -842,7 +829,7 @@ static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, voi
}
list_add_before(&expr->node.entry, &res->node.entry);
- replace_node(&expr->node, &res->node);
+ hlsl_replace_node(&expr->node, &res->node);
return true;
}
@@ -862,7 +849,7 @@ static bool remove_trivial_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *i
if (((swizzle->swizzle >> (2 * i)) & 3) != i)
return false;
- replace_node(instr, swizzle->val.node);
+ hlsl_replace_node(instr, swizzle->val.node);
return true;
}
--
2.34.1
4
9
[v2 PATCH vkd3d] vkd3d-shader/hlsl: Fix floating point literals matching.
by Nikolay Sivov 17 Feb '22
by Nikolay Sivov 17 Feb '22
17 Feb '22
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
v2: as far as I can tell from testing, it's not allowed to have
float literal suffixes without decimal point or exponent.
libs/vkd3d-shader/hlsl.l | 2 +-
tests/hlsl-initializer-numeric.shader_test | 13 +++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l
index e9281ec..1cc19ad 100644
--- a/libs/vkd3d-shader/hlsl.l
+++ b/libs/vkd3d-shader/hlsl.l
@@ -192,7 +192,7 @@ row_major {return KW_ROW_MAJOR; }
yylval->floatval = atof(yytext);
return C_FLOAT;
}
-[0-9]+([eE][+-]?[0-9]+)?[h|H|f|F] {
+[0-9]+[eE][+-]?[0-9]+[h|H|f|F]? {
yylval->floatval = atof(yytext);
return C_FLOAT;
}
diff --git a/tests/hlsl-initializer-numeric.shader_test b/tests/hlsl-initializer-numeric.shader_test
index 2fce390..4057688 100644
--- a/tests/hlsl-initializer-numeric.shader_test
+++ b/tests/hlsl-initializer-numeric.shader_test
@@ -33,3 +33,16 @@ float4 main() : sv_target
[test]
draw quad
probe all rgba (1.0, 2.0, 3.0, 4.0) 4
+
+
+[pixel shader]
+float4 main() : sv_target
+{
+ float4 aa = { 1e1, 1e-1, 1., 2.f };
+ float4 bb = { .1, .1e1, .2f, 1.e-1f };
+ return aa + bb;
+}
+
+[test]
+draw quad
+probe all rgba (10.1, 1.1, 1.2, 2.1) 4
--
2.34.1
5
4
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/scrrun/filesystem.c | 138 +++++++++++++++++++++++++++++++--
dlls/scrrun/tests/filesystem.c | 23 ++++--
2 files changed, 145 insertions(+), 16 deletions(-)
diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c
index d16ecb722dc..4794437a71d 100644
--- a/dlls/scrrun/filesystem.c
+++ b/dlls/scrrun/filesystem.c
@@ -706,20 +706,21 @@ static HRESULT WINAPI textstream_SkipLine(ITextStream *iface)
static HRESULT WINAPI textstream_Close(ITextStream *iface)
{
- struct textstream *This = impl_from_ITextStream(iface);
+ struct textstream *stream = impl_from_ITextStream(iface);
HRESULT hr = S_OK;
- TRACE("(%p)\n", This);
+ TRACE("%p.\n", iface);
- if(!CloseHandle(This->file))
+ if (!CloseHandle(stream->file))
hr = S_FALSE;
- This->file = NULL;
+ stream->file = NULL;
return hr;
}
-static const ITextStreamVtbl textstreamvtbl = {
+static const ITextStreamVtbl textstreamvtbl =
+{
textstream_QueryInterface,
textstream_AddRef,
textstream_Release,
@@ -742,6 +743,114 @@ static const ITextStreamVtbl textstreamvtbl = {
textstream_Close
};
+static HRESULT WINAPI pipestream_get_Line(ITextStream *iface, LONG *line)
+{
+ FIXME("%p, %p.\n", iface, line);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_get_Column(ITextStream *iface, LONG *column)
+{
+ FIXME("%p, %p.\n", iface, column);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_get_AtEndOfStream(ITextStream *iface, VARIANT_BOOL *eos)
+{
+ FIXME("%p, %p.\n", iface, eos);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_get_AtEndOfLine(ITextStream *iface, VARIANT_BOOL *eol)
+{
+ FIXME("%p, %p.\n", iface, eol);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_Read(ITextStream *iface, LONG len, BSTR *text)
+{
+ FIXME("%p, %ld, %p.\n", iface, len, text);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_ReadLine(ITextStream *iface, BSTR *text)
+{
+ FIXME("%p, %p.\n", iface, text);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_ReadAll(ITextStream *iface, BSTR *text)
+{
+ FIXME("%p, %p.\n", iface, text);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_Write(ITextStream *iface, BSTR text)
+{
+ FIXME("%p, %s.\n", iface, debugstr_w(text));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_WriteLine(ITextStream *iface, BSTR text)
+{
+ FIXME("%p, %s.\n", iface, debugstr_w(text));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_WriteBlankLines(ITextStream *iface, LONG lines)
+{
+ FIXME("%p, %ld.\n", iface, lines);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_Skip(ITextStream *iface, LONG count)
+{
+ FIXME("%p, %ld.\n", iface, count);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI pipestream_SkipLine(ITextStream *iface)
+{
+ FIXME("%p.\n", iface);
+
+ return E_NOTIMPL;
+}
+
+static const ITextStreamVtbl pipestreamvtbl =
+{
+ textstream_QueryInterface,
+ textstream_AddRef,
+ textstream_Release,
+ textstream_GetTypeInfoCount,
+ textstream_GetTypeInfo,
+ textstream_GetIDsOfNames,
+ textstream_Invoke,
+ pipestream_get_Line,
+ pipestream_get_Column,
+ pipestream_get_AtEndOfStream,
+ pipestream_get_AtEndOfLine,
+ pipestream_Read,
+ pipestream_ReadLine,
+ pipestream_ReadAll,
+ pipestream_Write,
+ pipestream_WriteLine,
+ pipestream_WriteBlankLines,
+ pipestream_Skip,
+ pipestream_SkipLine,
+ textstream_Close
+};
+
static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMode mode, Tristate format, ITextStream **ret)
{
static const unsigned short utf16bom = 0xfeff;
@@ -839,11 +948,24 @@ static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMod
return S_OK;
}
-HRESULT WINAPI DoOpenPipeStream(HANDLE pipe, IOMode mode, ITextStream **stream)
+HRESULT WINAPI DoOpenPipeStream(HANDLE pipe, IOMode mode, ITextStream **ret)
{
- FIXME("%p, %d, %p.\n", pipe, mode, stream);
+ struct textstream *stream;
- return E_NOTIMPL;
+ TRACE("%p, %d, %p.\n", pipe, mode, ret);
+
+ if (!(stream = calloc(1, sizeof(*stream))))
+ return E_OUTOFMEMORY;
+
+ stream->ITextStream_iface.lpVtbl = &pipestreamvtbl;
+ stream->ref = 1;
+ stream->mode = mode;
+ stream->file = pipe;
+
+ init_classinfo(&CLSID_TextStream, (IUnknown *)&stream->ITextStream_iface, &stream->classinfo);
+ *ret = &stream->ITextStream_iface;
+
+ return S_OK;
}
static HRESULT WINAPI drive_QueryInterface(IDrive *iface, REFIID riid, void **obj)
diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c
index 098060a90bb..894b6251f34 100644
--- a/dlls/scrrun/tests/filesystem.c
+++ b/dlls/scrrun/tests/filesystem.c
@@ -2613,7 +2613,6 @@ static void test_DoOpenPipeStream(void)
ok(ret, "Failed to create pipes.\n");
hr = pDoOpenPipeStream(piperead, ForReading, &stream_read);
- todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
{
@@ -2624,9 +2623,13 @@ static void test_DoOpenPipeStream(void)
ok(written == sizeof(testdata), "Write to anonymous pipe wrote %ld bytes.\n", written);
hr = ITextStream_Read(stream_read, 4, &str);
+ todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- ok(!wcscmp(str, L"test"), "Unexpected data read %s.\n", wine_dbgstr_w(str));
- SysFreeString(str);
+ if (SUCCEEDED(hr))
+ {
+ ok(!wcscmp(str, L"test"), "Unexpected data read %s.\n", wine_dbgstr_w(str));
+ SysFreeString(str);
+ }
ITextStream_Release(stream_read);
}
@@ -2635,7 +2638,6 @@ static void test_DoOpenPipeStream(void)
ok(ret, "Unexpected return value.\n");
/* Stream takes ownership. */
ret = CloseHandle(piperead);
- todo_wine
ok(!ret, "Unexpected return value.\n");
/* Streams on both ends. */
@@ -2644,32 +2646,37 @@ static void test_DoOpenPipeStream(void)
stream_read = NULL;
hr = pDoOpenPipeStream(piperead, ForReading, &stream_read);
- todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
stream_write = NULL;
hr = pDoOpenPipeStream(pipewrite, ForWriting, &stream_write);
- todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
{
str = SysAllocString(L"data");
hr = ITextStream_Write(stream_write, str);
+ todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = ITextStream_Write(stream_read, str);
+ todo_wine
ok(hr == CTL_E_BADFILEMODE, "Unexpected hr %#lx.\n", hr);
SysFreeString(str);
hr = ITextStream_Read(stream_write, 1, &str);
+ todo_wine
ok(hr == CTL_E_BADFILEMODE, "Unexpected hr %#lx.\n", hr);
hr = ITextStream_Read(stream_read, 4, &str);
+ todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- ok(!wcscmp(str, L"data"), "Unexpected data.\n");
- SysFreeString(str);
+ if (SUCCEEDED(hr))
+ {
+ ok(!wcscmp(str, L"data"), "Unexpected data.\n");
+ SysFreeString(str);
+ }
}
if (stream_read)
--
2.34.1
1
0
This serie fixes a couple of bugs in 64bit instance of winedbg handling
a 64 bit target.
The third one is mostly cosmetic (don't print 16 digits for 32 bit
addresses).
A+
---
Eric Pouech (3):
programs/winedbg: correctly read register values
dlls/dbghelp: correctly promote to 64bit register relative offsets
programs/winedbg: rework printing of pointer values
dlls/dbghelp/symbol.c | 2 +-
programs/winedbg/be_i386.c | 8 +++---
programs/winedbg/be_x86_64.c | 9 ++++---
programs/winedbg/break.c | 14 +++++-----
programs/winedbg/debugger.h | 6 ++---
programs/winedbg/gdbproxy.c | 9 ++++---
programs/winedbg/info.c | 17 ++++++------
programs/winedbg/memory.c | 49 +++++++----------------------------
programs/winedbg/stack.c | 11 ++++----
programs/winedbg/symbol.c | 10 +++----
programs/winedbg/tgt_active.c | 41 +++++++++++++++--------------
programs/winedbg/winedbg.c | 3 ++-
12 files changed, 78 insertions(+), 101 deletions(-)
1
3
[PATCH 1/5] dlls/ntdll/tests: fully allocate SYSTEM_FIRMWARE_TABLE_INFORMATION
by Eric Pouech 17 Feb '22
by Eric Pouech 17 Feb '22
17 Feb '22
this prevents mingw-gcc version 11 to generate warnings (-Warray-bounds)
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
---
dlls/ntdll/tests/info.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index e9d42127c3e..d6b323dd9d7 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -1461,7 +1461,7 @@ static void test_query_firmware(void)
NTSTATUS status;
SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti;
- sfti = HeapAlloc(GetProcessHeap(), 0, min_sfti_len);
+ sfti = HeapAlloc(GetProcessHeap(), 0, sizeof(*sfti));
ok(!!sfti, "Failed to allocate memory\n");
sfti->ProviderSignature = 0;
1
4
From: Santino Mazza <mazzasantino1206(a)gmail.com>
With this change now some applications which uses ncrypt for
signature validation work.
For example, the visual studio installer (using dotnet from winetricks).
Signed-off-by: Santino Mazza <mazzasantino1206(a)gmail.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/ncrypt/main.c | 8 ++++++++
dlls/ncrypt/ncrypt.spec | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c
index 2c2a0dc6f56..2a804109dec 100644
--- a/dlls/ncrypt/main.c
+++ b/dlls/ncrypt/main.c
@@ -367,3 +367,11 @@ SECURITY_STATUS WINAPI NCryptSetProperty(NCRYPT_HANDLE handle, const WCHAR *name
return set_object_property(object, name, input, insize);
}
+
+SECURITY_STATUS NCryptVerifySignature(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *hash, DWORD hash_size,
+ BYTE *signature, DWORD signature_size, DWORD flags)
+{
+ FIXME("(%#Ix, %p, %p, %lu, %p, %lu, %#lx): stub\n", handle, padding, hash, hash_size, signature,
+ signature_size, flags);
+ return ERROR_SUCCESS;
+}
diff --git a/dlls/ncrypt/ncrypt.spec b/dlls/ncrypt/ncrypt.spec
index 0e92609790c..bb914616373 100644
--- a/dlls/ncrypt/ncrypt.spec
+++ b/dlls/ncrypt/ncrypt.spec
@@ -101,7 +101,7 @@
@ stub NCryptUnprotectKey
@ stub NCryptUnprotectSecret
@ stub NCryptVerifyClaim
-@ stub NCryptVerifySignature
+@ stdcall NCryptVerifySignature(ptr ptr ptr long ptr long long)
@ stub SslChangeNotify
@ stub SslComputeClientAuthHash
@ stub SslComputeEapKeyBlock
--
2.30.2
1
0