[7/11] wineesd.drv: Simplify wodPlayer_WriteMaxFrags() and wodPlayer_FeedDSP().

Francois Gouget fgouget at codeweavers.com
Sat Mar 28 05:46:08 CDT 2009


We don't know how much free space we have in the EsounD buffer, so just 
write until it is full.
Sleep for a fraction of the time it will take for the buffer to drain so 
we can refill it in time.
---

This avoids hiccups.

 dlls/wineesd.drv/audio.c |  122 +++++++++++++++++++---------------------------
 1 files changed, 50 insertions(+), 72 deletions(-)

diff --git a/dlls/wineesd.drv/audio.c b/dlls/wineesd.drv/audio.c
index 7ef11c3..fd60831 100644
--- a/dlls/wineesd.drv/audio.c
+++ b/dlls/wineesd.drv/audio.c
@@ -774,44 +774,39 @@ static DWORD wodPlayer_NotifyWait(const WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr)
 
 /**************************************************************************
  * 			     wodPlayer_WriteMaxFrags            [internal]
- * Writes the maximum number of bytes possible to the DSP and returns
- * the number of bytes written.
+ *
+ * Esdlib will have set the stream socket buffer size to an appropriate
+ * value, so now our job is to keep it full. So write what we can, and
+ * return 1 if more can be written and 0 otherwise.
  */
-static int wodPlayer_WriteMaxFrags(WINE_WAVEOUT* wwo, DWORD* bytes)
+static int wodPlayer_WriteMaxFrags(WINE_WAVEOUT* wwo)
 {
-    /* Only attempt to write to free bytes */
     DWORD dwLength = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;
-    int toWrite = min(dwLength, *bytes);
     int written;
 
     TRACE("Writing wavehdr %p.%u[%u]\n",
           wwo->lpPlayPtr, wwo->dwPartialOffset, wwo->lpPlayPtr->dwBufferLength);
 
-    /* send the audio data to esd for playing */
-    TRACE("toWrite == %d\n", toWrite);
-    written = write(wwo->stream_fd, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toWrite);
-
-    TRACE("written = %d\n", written);
-
-    if (written <= 0) 
+    written = write(wwo->stream_fd, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, dwLength);
+    if (written <= 0)
     {
-      *bytes = 0; /* apparently esd is actually full */
-      return written; /* if we wrote nothing just return */
+        /* the esd buffer is full or some error occurred */
+        TRACE("write(%u) failed, errno=%d\n", dwLength, errno);
+        return 0;
     }
-
-    if (written >= dwLength)
-        wodPlayer_PlayPtrNext(wwo);   /* If we wrote all current wavehdr, skip to the next one */
-    else
-        wwo->dwPartialOffset += written;    /* Remove the amount written */
-
-    if (written < toWrite)
-	*bytes = 0;
-    else
-	*bytes -= written;
+    TRACE("Wrote %d bytes out of %u\n", written, dwLength);
 
     wwo->dwWrittenTotal += written; /* update stats on this wave device */
+    if (written == dwLength)
+    {
+        /* We're done with this wavehdr, skip to the next one */
+        wodPlayer_PlayPtrNext(wwo);
+        return 1;
+    }
 
-    return written; /* return the number of bytes written */
+    /* Remove the amount written and wait a bit before trying to write more */
+    wwo->dwPartialOffset += written;
+    return 0;
 }
 
 
@@ -1002,58 +997,32 @@ static void wodPlayer_ProcessMessages(WINE_WAVEOUT* wwo)
  */
 static DWORD wodPlayer_FeedDSP(WINE_WAVEOUT* wwo)
 {
-    DWORD       availInQ;
-
     wodUpdatePlayedTotal(wwo);
-    /* better way to set availInQ? */
-    availInQ = ESD_BUF_SIZE;
-    TRACE("availInQ = %d\n", availInQ);
-
-    /* input queue empty */
-    if (!wwo->lpPlayPtr) {
-        TRACE("Run out of wavehdr:s... flushing\n");
-        return INFINITE;
-    }
-
-#if 0
-    /* no more room... no need to try to feed */
-    if(!availInQ)
-    {
-	TRACE("no more room, no need to try to feed\n");
-	return wwo->dwSleepTime;
-    }
-#endif
-
-    /* Feed from partial wavehdr */
-    if (wwo->lpPlayPtr && wwo->dwPartialOffset != 0)
-    {
-        TRACE("feeding from partial wavehdr\n");
-        wodPlayer_WriteMaxFrags(wwo, &availInQ);
-    }
 
     /* Feed wavehdrs until we run out of wavehdrs or DSP space */
-    if (!wwo->dwPartialOffset)
+    while (wwo->lpPlayPtr)
     {
-	while(wwo->lpPlayPtr && availInQ)
-	{
-	    TRACE("feeding waveheaders until we run out of space\n");
-	    /* note the value that dwPlayedTotal will return when this wave finishes playing */
-	    wwo->lpPlayPtr->reserved = wwo->dwWrittenTotal + wwo->lpPlayPtr->dwBufferLength;
-            TRACE("reserved=(%ld) dwWrittenTotal=(%d) dwBufferLength=(%d)\n",
-		  wwo->lpPlayPtr->reserved,
-		  wwo->dwWrittenTotal,
-		  wwo->lpPlayPtr->dwBufferLength
-		);
-	    wodPlayer_WriteMaxFrags(wwo, &availInQ);
-	}
-    }
-
-    if (!wwo->lpPlayPtr) {
-        TRACE("Ran out of wavehdrs\n");
-        return INFINITE;
+        if (wwo->dwPartialOffset != 0)
+            TRACE("feeding from partial wavehdr\n");
+        else
+        {
+            /* Note the value that dwPlayedTotal will return when this
+             * wavehdr finishes playing, for the completion notifications.
+             */
+            wwo->lpPlayPtr->reserved = wwo->dwWrittenTotal + wwo->lpPlayPtr->dwBufferLength;
+            TRACE("new wavehdr: reserved=(%ld) dwWrittenTotal=(%d) dwBufferLength=(%d)\n",
+                  wwo->lpPlayPtr->reserved, wwo->dwWrittenTotal,
+                  wwo->lpPlayPtr->dwBufferLength);
+        }
+        if (!wodPlayer_WriteMaxFrags(wwo))
+        {
+            /* the buffer is full, wait a bit */
+            return wwo->dwSleepTime;
+        }
     }
 
-    return wwo->dwSleepTime;
+    TRACE("Ran out of wavehdrs or nothing to play\n");
+    return INFINITE;
 }
 
 
@@ -1118,6 +1087,7 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
     int			out_bits = ESD_BITS8, out_channels = ESD_MONO, out_rate;
     int			out_mode = ESD_STREAM, out_func = ESD_PLAY;
     esd_format_t	out_format;
+    int			mode;
 
     TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
     if (lpDesc == NULL) {
@@ -1193,7 +1163,15 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
     wwo->dwPlayedTotal = 0;
     wwo->dwWrittenTotal = 0;
 
-    wwo->dwSleepTime = (1024 * 1000 * BUFFER_REFILL_THRESHOLD) / wwo->waveFormat.Format.nAvgBytesPerSec;
+    /* ESD_BUF_SIZE is the socket buffer size in samples. Set dwSleepTime
+     * to a fraction of that so it never get empty.
+     */
+    wwo->dwSleepTime = 1000 * ESD_BUF_SIZE / out_rate / 3;
+
+    /* Set the stream socket to O_NONBLOCK, so we can stop playing smoothly */
+    mode = fcntl(wwo->stream_fd, F_GETFL);
+    mode |= O_NONBLOCK;
+    fcntl(wwo->stream_fd, F_SETFL, mode);
 
     ESD_InitRingMessage(&wwo->msgRing);
 
-- 
1.6.2




More information about the wine-patches mailing list