[PATCH 3/3] winealsa.drv: Add support for non-mmap mode in dscapture
Maarten Lankhorst (none)
mlankhorst at patser.
Tue Sep 22 17:11:00 CDT 2009
---
dlls/winealsa.drv/dscapture.c | 102 ++++++++++++++++++++++++++++++++---------
1 files changed, 80 insertions(+), 22 deletions(-)
diff --git a/dlls/winealsa.drv/dscapture.c b/dlls/winealsa.drv/dscapture.c
index 75eae36..48eb971 100644
--- a/dlls/winealsa.drv/dscapture.c
+++ b/dlls/winealsa.drv/dscapture.c
@@ -92,6 +92,7 @@ struct IDsCaptureDriverBufferImpl
CRITICAL_SECTION pcm_crst;
LPBYTE mmap_buffer, presented_buffer;
DWORD mmap_buflen_bytes, play_looping, mmap_ofs_bytes;
+ BOOL mmap;
/* Note: snd_pcm_frames_to_bytes(This->pcm, mmap_buflen_frames) != mmap_buflen_bytes */
/* The actual buffer may differ in size from the wanted buffer size */
@@ -311,6 +312,8 @@ static void CopyData(const IDsCaptureDriverBufferImpl* This, snd_pcm_uframes_t f
DWORD realbuflen = snd_pcm_frames_to_bytes(This->pcm, This->mmap_buflen_frames);
DWORD realofs = snd_pcm_frames_to_bytes(This->pcm, fromwhere);
+ assert(This->mmap);
+
if (remainder >= dlen)
{
CopyDataWrap(This, This->presented_buffer + ofs, realofs, dlen, realbuflen);
@@ -341,20 +344,52 @@ static snd_pcm_uframes_t CommitAll(IDsCaptureDriverBufferImpl *This, DWORD force
if (used < commitahead && (forced || This->play_looping))
{
snd_pcm_uframes_t done, putin = commitahead - used;
- snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
- CopyData(This, This->mmap_pos, putin);
- done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
+ if (This->mmap)
+ {
+ snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
+ CopyData(This, This->mmap_pos, putin);
+ done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
+ }
+ else
+ {
+ int ret;
+
+ if (This->mmap_pos + putin > This->mmap_buflen_frames)
+ putin = This->mmap_buflen_frames - This->mmap_pos;
+ ret = snd_pcm_readi(This->pcm, This->presented_buffer + This->mmap_pos, putin);
+ if (ret == -EPIPE)
+ {
+ WARN("Underrun occurred\n");
+ snd_pcm_prepare(This->pcm);
+ ret = snd_pcm_readi(This->pcm, This->presented_buffer + This->mmap_pos, putin);
+ snd_pcm_start(This->pcm);
+ }
+ if (ret < 0)
+ WARN("Committing data: %d / %s (%ld)\n", ret, snd_strerror(ret), putin);
+ done = putin;
+ }
This->mmap_pos += done;
used += done;
putin = commitahead - used;
if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0 && This->play_looping)
{
- snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
This->mmap_ofs_bytes += snd_pcm_frames_to_bytes(This->pcm, This->mmap_buflen_frames);
This->mmap_ofs_bytes %= This->mmap_buflen_bytes;
- CopyData(This, This->mmap_pos, putin);
- done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
+
+ if (This->mmap)
+ {
+ snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
+ CopyData(This, This->mmap_pos, putin);
+ done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin);
+ }
+ else
+ {
+ This->mmap_pos = 0;
+ snd_pcm_readi(This->pcm, This->presented_buffer, putin);
+ done = putin;
+ }
+
This->mmap_pos += done;
used += done;
}
@@ -450,23 +485,30 @@ static int CreateMMAP(IDsCaptureDriverBufferImpl* pdbi)
snd_pcm_sw_params_set_avail_min(pcm, sw_params, 0);
err = snd_pcm_sw_params(pcm, sw_params);
- avail = snd_pcm_avail_update(pcm);
- if ((snd_pcm_sframes_t)avail < 0)
+ pdbi->mmap_ofs_bytes = 0;
+ if (!pdbi->mmap)
{
- ERR("No buffer is available: %s.\n", snd_strerror(avail));
- return DSERR_GENERIC;
+ pdbi->mmap_buffer = NULL;
+
+ frames = snd_pcm_bytes_to_frames(pdbi->pcm, pdbi->mmap_buflen_bytes);
+ snd_pcm_format_set_silence(format, pdbi->presented_buffer, frames);
+ pdbi->mmap_pos = 0;
}
- err = snd_pcm_mmap_begin(pcm, &areas, &ofs, &avail);
- if ( err < 0 )
+ else
{
- ERR("Can't map sound device for direct access: %s\n", snd_strerror(err));
- return DSERR_GENERIC;
+ err = snd_pcm_mmap_begin(pcm, &areas, &ofs, &avail);
+ if ( err < 0 )
+ {
+ ERR("Can't map sound device for direct access: %s/%d\n", snd_strerror(err), err);
+ return DSERR_GENERIC;
+ }
+ snd_pcm_format_set_silence(format, areas->addr, pdbi->mmap_buflen_frames);
+ pdbi->mmap_pos = ofs + snd_pcm_mmap_commit(pcm, ofs, 0);
+ pdbi->mmap_buffer = areas->addr;
}
- err = snd_pcm_mmap_commit(pcm, ofs, 0);
- pdbi->mmap_buffer = areas->addr;
TRACE("created mmap buffer of %ld frames (%d bytes) at %p\n",
- frames, pdbi->mmap_buflen_bytes, pdbi->mmap_buffer);
+ pdbi->mmap_buflen_frames, pdbi->mmap_buflen_bytes, pdbi->mmap_buffer);
return DS_OK;
}
@@ -590,6 +632,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_SetFormat(PIDSCDRIVERBUFFER ifa
snd_pcm_uframes_t buffer_size;
DWORD rate = pwfx->nSamplesPerSec;
int err=0;
+ BOOL mmap;
TRACE("(%p, %p)\n", iface, pwfx);
@@ -631,9 +674,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_SetFormat(PIDSCDRIVERBUFFER ifa
/* Set some defaults */
snd_pcm_hw_params_any(pcm, hw_params);
- err = snd_pcm_hw_params_set_access (pcm, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED);
- if (err < 0) goto err;
-
+
err = snd_pcm_hw_params_set_channels(pcm, hw_params, pwfx->nChannels);
if (err < 0) { WARN("Could not set channels to %d\n", pwfx->nChannels); goto err; }
@@ -656,9 +697,21 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_SetFormat(PIDSCDRIVERBUFFER ifa
snd_pcm_hw_params_set_buffer_size_near(pcm, hw_params, &buffer_size);
buffer_size = 5000;
snd_pcm_hw_params_set_period_time_near(pcm, hw_params, (unsigned int*)&buffer_size, NULL);
+
+ err = snd_pcm_hw_params_set_access (pcm, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED);
+ if (err < 0)
+ {
+ err = snd_pcm_hw_params_set_access (pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (err < 0) goto err;
+ mmap = 0;
+ }
+ else
+ mmap = 1;
+
err = snd_pcm_hw_params(pcm, hw_params);
+ if (err < 0) goto err;
err = snd_pcm_sw_params(pcm, This->sw_params);
- snd_pcm_prepare(pcm);
+ if (err < 0) goto err;
if (This->pcm)
{
@@ -666,6 +719,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_SetFormat(PIDSCDRIVERBUFFER ifa
snd_pcm_close(This->pcm);
}
This->pcm = pcm;
+ This->mmap = mmap;
snd_pcm_prepare(This->pcm);
CreateMMAP(This);
@@ -892,7 +946,11 @@ static HRESULT WINAPI IDsCaptureDriverImpl_Open(PIDSCDRIVER iface)
err = snd_pcm_hw_params_any(pcm, hw_params);
if (err < 0) goto err;
err = snd_pcm_hw_params_set_access (pcm, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED);
- if (err < 0) goto err;
+ if (err < 0)
+ {
+ err = snd_pcm_hw_params_set_access (pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (err < 0) goto err;
+ }
TRACE("Success\n");
snd_pcm_close(pcm);
--
1.6.3.3
--------------050802030505010508080008--
More information about the wine-patches
mailing list