[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