Ken Thomases : winecoreaudio: Leave audio unit running, except when waveout device paused.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Dec 21 10:36:32 CST 2006


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

Author: Ken Thomases <ken at codeweavers.com>
Date:   Thu Dec 21 03:48:59 2006 -0600

winecoreaudio: Leave audio unit running, except when waveout device paused.

---

 dlls/winmm/winecoreaudio/audio.c |   89 +++++++++++++++++++++----------------
 1 files changed, 50 insertions(+), 39 deletions(-)

diff --git a/dlls/winmm/winecoreaudio/audio.c b/dlls/winmm/winecoreaudio/audio.c
index 265b9af..d38fe9b 100644
--- a/dlls/winmm/winecoreaudio/audio.c
+++ b/dlls/winmm/winecoreaudio/audio.c
@@ -722,6 +722,17 @@ static DWORD wodOpen(WORD wDevID, LPWAVE
         return WAVERR_BADFORMAT; /* FIXME return an error based on the OSStatus */
     }
     wwo->streamDescription = streamFormat;
+
+    ret = AudioOutputUnitStart(wwo->audioUnit);
+    if (ret)
+    {
+        ERR("AudioOutputUnitStart failed: %08x\n", ret);
+        AudioUnitUninitialize(wwo->audioUnit);
+        AudioUnit_CloseAudioUnit(wwo->audioUnit);
+        pthread_mutex_unlock(&wwo->lock);
+        return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
+    }
+
     wwo->state = WINE_WS_STOPPED;
                 
     wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
@@ -915,14 +926,7 @@ static void wodHelper_PlayPtrNext(WINE_W
         wwo->lpPlayPtr = wwo->lpPlayPtr->lpNext;
 
         if (!wwo->lpPlayPtr)
-        {
-            OSStatus status;
             wwo->state = WINE_WS_STOPPED;
-            status = AudioOutputUnitStop(wwo->audioUnit);
-            if (status && wwo->err_on)
-                fprintf(stderr, "err:winecoreaudio:wodHelper_PlayPtrNext AudioOutputUnitStop return %c%c%c%c\n",
-                        (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
-        }
         else
             wodHelper_CheckForLoopBegin(wwo);
     }
@@ -1022,12 +1026,12 @@ static  DWORD  wodHelper_Reset(WINE_WAVE
         wwo->state = WINE_WS_PAUSED;
     }
 
-    status = AudioOutputUnitStop(wwo->audioUnit);
-
     pthread_mutex_unlock(&wwo->lock);
 
+    status = AudioOutputUnitStart(wwo->audioUnit);
+
     if (status) {
-        ERR( "AudioOutputUnitStop return %c%c%c%c\n",
+        ERR( "AudioOutputUnitStart return %c%c%c%c\n",
              (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
         return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
     }
@@ -1083,13 +1087,7 @@ static DWORD wodWrite(WORD wDevID, LPWAV
         wwo->lpPlayPtr = lpWaveHdr;
 
         if (wwo->state == WINE_WS_STOPPED)
-        {
-            OSStatus status = AudioOutputUnitStart(wwo->audioUnit);
-            if (status) {
-                ERR("AudioOutputUnitStart return %c%c%c%c\n", (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
-            }
-            else wwo->state = WINE_WS_PLAYING;
-        }
+            wwo->state = WINE_WS_PLAYING;
 
         wodHelper_CheckForLoopBegin(wwo);
 
@@ -1114,21 +1112,26 @@ static DWORD wodPause(WORD wDevID)
         WARN("bad device ID !\n");
         return MMSYSERR_BADDEVICEID;
     }
-    
+
+    /* The order of the following operations is important since we can't hold
+     * the mutex while we make an Audio Unit call.  Stop the Audio Unit before
+     * setting the PAUSED state.  In wodRestart, the order is reversed.  This
+     * guarantees that we can't get into a situation where the state is
+     * PLAYING or STOPPED but the Audio Unit isn't running.  Although we can
+     * be in PAUSED state with the Audio Unit still running, that's harmless
+     * because the render callback will just produce silence.
+     */
+    status = AudioOutputUnitStop(WOutDev[wDevID].audioUnit);
+    if (status) {
+        WARN("AudioOutputUnitStop return %c%c%c%c\n",
+             (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
+    }
+
     pthread_mutex_lock(&WOutDev[wDevID].lock);
     if (WOutDev[wDevID].state == WINE_WS_PLAYING || WOutDev[wDevID].state == WINE_WS_STOPPED)
-    {
         WOutDev[wDevID].state = WINE_WS_PAUSED;
-        status = AudioOutputUnitStop(WOutDev[wDevID].audioUnit);
-        if (status) {
-            ERR( "AudioOutputUnitStop return %c%c%c%c\n",
-                 (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
-            pthread_mutex_unlock(&WOutDev[wDevID].lock);
-            return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
-        }
-    }
     pthread_mutex_unlock(&WOutDev[wDevID].lock);
-    
+
     return MMSYSERR_NOERROR;
 }
 
@@ -1137,6 +1140,8 @@ static DWORD wodPause(WORD wDevID)
 */
 static DWORD wodRestart(WORD wDevID)
 {
+    OSStatus status;
+
     TRACE("(%u);\n", wDevID);
     
     if (wDevID >= MAX_WAVEOUTDRV )
@@ -1144,26 +1149,32 @@ static DWORD wodRestart(WORD wDevID)
         WARN("bad device ID !\n");
         return MMSYSERR_BADDEVICEID;
     }
-    
+
+    /* The order of the following operations is important since we can't hold
+     * the mutex while we make an Audio Unit call.  Set the PLAYING/STOPPED
+     * state before starting the Audio Unit.  In wodPause, the order is
+     * reversed.  This guarantees that we can't get into a situation where
+     * the state is PLAYING or STOPPED but the Audio Unit isn't running.
+     * Although we can be in PAUSED state with the Audio Unit still running,
+     * that's harmless because the render callback will just produce silence.
+     */
     pthread_mutex_lock(&WOutDev[wDevID].lock);
     if (WOutDev[wDevID].state == WINE_WS_PAUSED)
     {
         if (WOutDev[wDevID].lpPlayPtr)
-        {
-            OSStatus status = AudioOutputUnitStart(WOutDev[wDevID].audioUnit);
-            if (status) {
-                ERR("AudioOutputUnitStart return %c%c%c%c\n",
-                    (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
-                pthread_mutex_unlock(&WOutDev[wDevID].lock);
-                return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
-            }
             WOutDev[wDevID].state = WINE_WS_PLAYING;
-        }
         else
             WOutDev[wDevID].state = WINE_WS_STOPPED;
     }
     pthread_mutex_unlock(&WOutDev[wDevID].lock);
-    
+
+    status = AudioOutputUnitStart(WOutDev[wDevID].audioUnit);
+    if (status) {
+        ERR("AudioOutputUnitStart return %c%c%c%c\n",
+            (char) (status >> 24), (char) (status >> 16), (char) (status >> 8), (char) status);
+        return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
+    }
+
     return MMSYSERR_NOERROR;
 }
 




More information about the wine-cvs mailing list