Module: wine
Branch: master
Commit: 5c4ed3bcce380b8ff834654f8dbd72bff5302989
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5c4ed3bcce380b8ff834654f8…
Author: Ken Thomases <ken(a)codeweavers.com>
Date: Sat Apr 11 07:18:27 2009 -0500
winecoreaudio: For waveOut, don't use STOPPED state; it's redundant.
The distinction between PLAYING and STOPPED has always been whether
lpPlayPtr is NULL, so just use that instead of two states.
---
dlls/winecoreaudio.drv/audio.c | 41 ++++++++++++++-------------------------
1 files changed, 15 insertions(+), 26 deletions(-)
diff --git a/dlls/winecoreaudio.drv/audio.c b/dlls/winecoreaudio.drv/audio.c
index 9b55326..f3a63a4 100644
--- a/dlls/winecoreaudio.drv/audio.c
+++ b/dlls/winecoreaudio.drv/audio.c
@@ -87,22 +87,21 @@ AudioUnitRender( AudioUnit ci,
* +---------+-------------+---------------+---------------------------------+
* | state | function | event | new state |
* +---------+-------------+---------------+---------------------------------+
-* | | open() | | STOPPED |
+* | | open() | | PLAYING |
* | PAUSED | write() | | PAUSED |
-* | STOPPED | write() | <thrd create> | PLAYING |
* | PLAYING | write() | HEADER | PLAYING |
* | (other) | write() | <error> | |
* | (any) | pause() | PAUSING | PAUSED |
-* | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
-* | (any) | reset() | RESETTING | STOPPED |
+* | PAUSED | restart() | RESTARTING | PLAYING |
+* | (any) | reset() | RESETTING | PLAYING |
* | (any) | close() | CLOSING | CLOSED |
* +---------+-------------+---------------+---------------------------------+
*/
/* states of the playing device */
-#define WINE_WS_PLAYING 0
+#define WINE_WS_PLAYING 0 /* for waveOut: lpPlayPtr == NULL -> stopped */
#define WINE_WS_PAUSED 1
-#define WINE_WS_STOPPED 2
+#define WINE_WS_STOPPED 2 /* Not used for waveOut */
#define WINE_WS_CLOSED 3
#define WINE_WS_OPENING 4
#define WINE_WS_CLOSING 5
@@ -888,7 +887,7 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
wwo->audioUnit = audioUnit;
wwo->streamDescription = streamFormat;
- wwo->state = WINE_WS_STOPPED;
+ wwo->state = WINE_WS_PLAYING;
wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
@@ -1101,9 +1100,7 @@ static void wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
/* We didn't loop back. Advance to the next wave header */
wwo->lpPlayPtr = wwo->lpPlayPtr->lpNext;
- if (!wwo->lpPlayPtr)
- wwo->state = WINE_WS_STOPPED;
- else
+ if (wwo->lpPlayPtr)
wodHelper_CheckForLoopBegin(wwo);
}
}
@@ -1228,9 +1225,6 @@ static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
{
wwo->lpPlayPtr = lpWaveHdr;
- if (wwo->state == WINE_WS_STOPPED)
- wwo->state = WINE_WS_PLAYING;
-
wodHelper_CheckForLoopBegin(wwo);
wwo->dwPartialOffset = 0;
@@ -1259,9 +1253,9 @@ static DWORD wodPause(WORD wDevID)
* 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.
+ * PLAYING 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) {
@@ -1270,7 +1264,7 @@ static DWORD wodPause(WORD wDevID)
}
OSSpinLockLock(&WOutDev[wDevID].lock);
- if (WOutDev[wDevID].state == WINE_WS_PLAYING || WOutDev[wDevID].state == WINE_WS_STOPPED)
+ if (WOutDev[wDevID].state == WINE_WS_PLAYING)
WOutDev[wDevID].state = WINE_WS_PAUSED;
OSSpinLockUnlock(&WOutDev[wDevID].lock);
@@ -1293,21 +1287,16 @@ static DWORD wodRestart(WORD wDevID)
}
/* 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
+ * the mutex while we make an Audio Unit call. Set the PLAYING
* 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.
+ * the state is PLAYING 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.
*/
OSSpinLockLock(&WOutDev[wDevID].lock);
if (WOutDev[wDevID].state == WINE_WS_PAUSED)
- {
- if (WOutDev[wDevID].lpPlayPtr)
- WOutDev[wDevID].state = WINE_WS_PLAYING;
- else
- WOutDev[wDevID].state = WINE_WS_STOPPED;
- }
+ WOutDev[wDevID].state = WINE_WS_PLAYING;
OSSpinLockUnlock(&WOutDev[wDevID].lock);
status = AudioOutputUnitStart(WOutDev[wDevID].audioUnit);
@@ -1351,7 +1340,7 @@ static DWORD wodReset(WORD wDevID)
lpSavedQueuePtr = wwo->lpQueuePtr;
wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
- wwo->state = WINE_WS_STOPPED;
+ wwo->state = WINE_WS_PLAYING;
wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0;
wwo->dwPartialOffset = 0; /* Clear partial wavehdr */
Module: wine
Branch: master
Commit: 06d705e7dfc3febfbf3592de942a3100dffde5b3
URL: http://source.winehq.org/git/wine.git/?a=commit;h=06d705e7dfc3febfbf3592de9…
Author: Ken Thomases <ken(a)codeweavers.com>
Date: Sat Apr 11 07:18:23 2009 -0500
winecoreaudio: Avoid a race between closing and opening the waveOut device.
---
dlls/winecoreaudio.drv/audio.c | 22 ++++++++++++++++------
1 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/dlls/winecoreaudio.drv/audio.c b/dlls/winecoreaudio.drv/audio.c
index e81aa3e..9b55326 100644
--- a/dlls/winecoreaudio.drv/audio.c
+++ b/dlls/winecoreaudio.drv/audio.c
@@ -105,6 +105,7 @@ AudioUnitRender( AudioUnit ci,
#define WINE_WS_STOPPED 2
#define WINE_WS_CLOSED 3
#define WINE_WS_OPENING 4
+#define WINE_WS_CLOSING 5
typedef struct tagCoreAudio_Device {
char dev_name[32];
@@ -957,14 +958,17 @@ static DWORD wodClose(WORD wDevID)
} else
{
OSStatus err;
+ AudioUnit audioUnit = wwo->audioUnit;
+
/* sanity check: this should not happen since the device must have been reset before */
if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
- wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
+ wwo->state = WINE_WS_CLOSING; /* mark the device as closing */
+ wwo->audioUnit = NULL;
OSSpinLockUnlock(&wwo->lock);
- err = AudioUnitUninitialize(wwo->audioUnit);
+ err = AudioUnitUninitialize(audioUnit);
if (err) {
ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24),
(char) (err >> 16),
@@ -973,12 +977,17 @@ static DWORD wodClose(WORD wDevID)
return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
}
- if ( !AudioUnit_CloseAudioUnit(wwo->audioUnit) )
+ if ( !AudioUnit_CloseAudioUnit(audioUnit) )
{
ERR("Can't close AudioUnit\n");
return MMSYSERR_ERROR; /* FIXME return an error based on the OSStatus */
}
+ OSSpinLockLock(&wwo->lock);
+ assert(wwo->state == WINE_WS_CLOSING);
+ wwo->state = WINE_WS_CLOSED; /* mark the device as closed */
+ OSSpinLockUnlock(&wwo->lock);
+
ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);
}
@@ -1332,7 +1341,8 @@ static DWORD wodReset(WORD wDevID)
OSSpinLockLock(&wwo->lock);
- if (wwo->state == WINE_WS_CLOSED || wwo->state == WINE_WS_OPENING)
+ if (wwo->state == WINE_WS_CLOSED || wwo->state == WINE_WS_CLOSING ||
+ wwo->state == WINE_WS_OPENING)
{
OSSpinLockUnlock(&wwo->lock);
WARN("resetting a closed device\n");
@@ -1631,8 +1641,8 @@ OSStatus CoreAudio_woAudioUnitIOProc(void *inRefCon,
OSSpinLockLock(&wwo->lock);
/* We might have been called before wwo has been completely filled out by
- * wodOpen. We have to do nothing in that case. The check of wwo->state
- * below ensures that. */
+ * wodOpen, or while it's being closed in wodClose. We have to do nothing
+ * in that case. The check of wwo->state below ensures that. */
while (dataNeeded > 0 && wwo->state == WINE_WS_PLAYING && wwo->lpPlayPtr)
{
unsigned int available = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;