Andrew Eikum : wineoss.drv: Only write as much data as will fit into the OSS buffer.

Alexandre Julliard julliard at winehq.org
Wed Oct 12 14:31:17 CDT 2011


Module: wine
Branch: master
Commit: 1ed42313a91dab5c0ceb98a0735db97d6cff060f
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1ed42313a91dab5c0ceb98a0735db97d6cff060f

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Tue Oct 11 15:31:28 2011 -0500

wineoss.drv: Only write as much data as will fit into the OSS buffer.

---

 dlls/wineoss.drv/mmdevdrv.c |   45 ++++++++++++++++++++++++++++--------------
 1 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c
index 6f8e2d2..f8316ee 100644
--- a/dlls/wineoss.drv/mmdevdrv.c
+++ b/dlls/wineoss.drv/mmdevdrv.c
@@ -1253,51 +1253,66 @@ static void oss_silence_buffer(ACImpl *This, BYTE *buf, UINT32 frames)
 
 static void oss_write_data(ACImpl *This)
 {
-    ssize_t written;
+    ssize_t written_bytes;
     UINT32 written_frames;
-    size_t to_write;
+    size_t to_write_frames, to_write_bytes;
+    audio_buf_info bi;
     BYTE *buf =
         This->local_buffer + (This->lcl_offs_frames * This->fmt->nBlockAlign);
 
     if(This->lcl_offs_frames + This->held_frames > This->bufsize_frames)
-        to_write = This->bufsize_frames - This->lcl_offs_frames;
+        to_write_frames = This->bufsize_frames - This->lcl_offs_frames;
     else
-        to_write = This->held_frames;
+        to_write_frames = This->held_frames;
+    to_write_bytes = to_write_frames * This->fmt->nBlockAlign;
+
+    if(ioctl(This->fd, SNDCTL_DSP_GETOSPACE, &bi) < 0){
+        WARN("GETOSPACE failed: %d (%s)\n", errno, strerror(errno));
+        return;
+    }
+
+    if(bi.bytes < to_write_bytes){
+        to_write_frames = bi.bytes / This->fmt->nBlockAlign;
+        to_write_bytes = to_write_frames * This->fmt->nBlockAlign;
+    }
 
     if(This->session->mute)
-        oss_silence_buffer(This, buf, to_write);
+        oss_silence_buffer(This, buf, to_write_frames);
 
-    written = write(This->fd, buf, to_write * This->fmt->nBlockAlign);
-    if(written < 0){
+    written_bytes = write(This->fd, buf, to_write_bytes);
+    if(written_bytes < 0){
         /* EAGAIN is OSS buffer full, log that too */
         WARN("write failed: %d (%s)\n", errno, strerror(errno));
         return;
     }
-    written_frames = written / This->fmt->nBlockAlign;
+    written_frames = written_bytes / This->fmt->nBlockAlign;
 
     This->lcl_offs_frames += written_frames;
     This->lcl_offs_frames %= This->bufsize_frames;
     This->held_frames -= written_frames;
     This->inbuf_frames += written_frames;
 
-    if(written_frames < to_write){
+    if(written_frames < to_write_frames){
         /* OSS buffer probably full */
         return;
     }
 
-    if(This->held_frames){
+    bi.bytes -= written_bytes;
+    if(This->held_frames && bi.bytes >= This->fmt->nBlockAlign){
         /* wrapped and have some data back at the start to write */
 
+        to_write_frames = bi.bytes / This->fmt->nBlockAlign;
+        to_write_bytes = to_write_frames * This->fmt->nBlockAlign;
+
         if(This->session->mute)
-            oss_silence_buffer(This, This->local_buffer, This->held_frames);
+            oss_silence_buffer(This, This->local_buffer, to_write_frames);
 
-        written = write(This->fd, This->local_buffer,
-                This->held_frames * This->fmt->nBlockAlign);
-        if(written < 0){
+        written_bytes = write(This->fd, This->local_buffer, to_write_bytes);
+        if(written_bytes < 0){
             WARN("write failed: %d (%s)\n", errno, strerror(errno));
             return;
         }
-        written_frames = written / This->fmt->nBlockAlign;
+        written_frames = written_bytes / This->fmt->nBlockAlign;
 
         This->lcl_offs_frames += written_frames;
         This->lcl_offs_frames %= This->bufsize_frames;




More information about the wine-cvs mailing list