winecoreaudio: Avoid a race between closing and opening the waveIn device.
This commit is contained in:
parent
5c4ed3bcce
commit
dff10db044
|
@ -1983,6 +1983,7 @@ static DWORD widClose(WORD wDevID)
|
||||||
{
|
{
|
||||||
DWORD ret = MMSYSERR_NOERROR;
|
DWORD ret = MMSYSERR_NOERROR;
|
||||||
WINE_WAVEIN* wwi;
|
WINE_WAVEIN* wwi;
|
||||||
|
OSStatus err;
|
||||||
|
|
||||||
TRACE("(%u);\n", wDevID);
|
TRACE("(%u);\n", wDevID);
|
||||||
|
|
||||||
|
@ -1994,7 +1995,7 @@ static DWORD widClose(WORD wDevID)
|
||||||
|
|
||||||
wwi = &WInDev[wDevID];
|
wwi = &WInDev[wDevID];
|
||||||
OSSpinLockLock(&wwi->lock);
|
OSSpinLockLock(&wwi->lock);
|
||||||
if (wwi->state == WINE_WS_CLOSED)
|
if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
|
||||||
{
|
{
|
||||||
WARN("Device already closed.\n");
|
WARN("Device already closed.\n");
|
||||||
ret = MMSYSERR_INVALHANDLE;
|
ret = MMSYSERR_INVALHANDLE;
|
||||||
|
@ -2006,36 +2007,50 @@ static DWORD widClose(WORD wDevID)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wwi->state = WINE_WS_CLOSED;
|
wwi->state = WINE_WS_CLOSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
OSSpinLockUnlock(&wwi->lock);
|
OSSpinLockUnlock(&wwi->lock);
|
||||||
|
|
||||||
if (ret == MMSYSERR_NOERROR)
|
if (ret != MMSYSERR_NOERROR)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
/* Clean up and close the audio unit. This has to be done without
|
||||||
|
* wwi->lock being held to avoid deadlock. AudioUnitUninitialize will
|
||||||
|
* grab an internal Core Audio lock while waiting for the device work
|
||||||
|
* thread to exit. Meanwhile the device work thread may be holding
|
||||||
|
* that lock and trying to grab the wwi->lock in the callback. */
|
||||||
|
err = AudioUnitUninitialize(wwi->audioUnit);
|
||||||
|
if (err)
|
||||||
{
|
{
|
||||||
OSStatus err = AudioUnitUninitialize(wwi->audioUnit);
|
ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24),
|
||||||
if (err)
|
(char) (err >> 16),
|
||||||
{
|
(char) (err >> 8),
|
||||||
ERR("AudioUnitUninitialize return %c%c%c%c\n", (char) (err >> 24),
|
(char) err);
|
||||||
(char) (err >> 16),
|
|
||||||
(char) (err >> 8),
|
|
||||||
(char) err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!AudioUnit_CloseAudioUnit(wwi->audioUnit))
|
|
||||||
{
|
|
||||||
ERR("Can't close AudioUnit\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dellocate our audio buffers */
|
|
||||||
widHelper_DestroyAudioBufferList(wwi->bufferList);
|
|
||||||
wwi->bufferList = NULL;
|
|
||||||
HeapFree(GetProcessHeap(), 0, wwi->bufferListCopy);
|
|
||||||
wwi->bufferListCopy = NULL;
|
|
||||||
|
|
||||||
ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!AudioUnit_CloseAudioUnit(wwi->audioUnit))
|
||||||
|
{
|
||||||
|
ERR("Can't close AudioUnit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OSSpinLockLock(&wwi->lock);
|
||||||
|
assert(wwi->state == WINE_WS_CLOSING);
|
||||||
|
|
||||||
|
/* Dellocate our audio buffers */
|
||||||
|
widHelper_DestroyAudioBufferList(wwi->bufferList);
|
||||||
|
wwi->bufferList = NULL;
|
||||||
|
HeapFree(GetProcessHeap(), 0, wwi->bufferListCopy);
|
||||||
|
wwi->bufferListCopy = NULL;
|
||||||
|
|
||||||
|
wwi->audioUnit = NULL;
|
||||||
|
wwi->state = WINE_WS_CLOSED;
|
||||||
|
OSSpinLockUnlock(&wwi->lock);
|
||||||
|
|
||||||
|
ret = widNotifyClient(wwi, WIM_CLOSE, 0L, 0L);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2069,7 +2084,7 @@ static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
|
||||||
wwi = &WInDev[wDevID];
|
wwi = &WInDev[wDevID];
|
||||||
OSSpinLockLock(&wwi->lock);
|
OSSpinLockLock(&wwi->lock);
|
||||||
|
|
||||||
if (wwi->state == WINE_WS_CLOSED)
|
if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
|
||||||
{
|
{
|
||||||
WARN("Trying to add buffer to closed device.\n");
|
WARN("Trying to add buffer to closed device.\n");
|
||||||
ret = MMSYSERR_INVALHANDLE;
|
ret = MMSYSERR_INVALHANDLE;
|
||||||
|
@ -2121,7 +2136,7 @@ static DWORD widStart(WORD wDevID)
|
||||||
wwi = &WInDev[wDevID];
|
wwi = &WInDev[wDevID];
|
||||||
OSSpinLockLock(&wwi->lock);
|
OSSpinLockLock(&wwi->lock);
|
||||||
|
|
||||||
if (wwi->state == WINE_WS_CLOSED)
|
if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
|
||||||
{
|
{
|
||||||
WARN("Trying to start closed device.\n");
|
WARN("Trying to start closed device.\n");
|
||||||
ret = MMSYSERR_INVALHANDLE;
|
ret = MMSYSERR_INVALHANDLE;
|
||||||
|
@ -2180,7 +2195,7 @@ static DWORD widStop(WORD wDevID)
|
||||||
|
|
||||||
OSSpinLockLock(&wwi->lock);
|
OSSpinLockLock(&wwi->lock);
|
||||||
|
|
||||||
if (wwi->state == WINE_WS_CLOSED)
|
if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
|
||||||
{
|
{
|
||||||
WARN("Trying to stop closed device.\n");
|
WARN("Trying to stop closed device.\n");
|
||||||
ret = MMSYSERR_INVALHANDLE;
|
ret = MMSYSERR_INVALHANDLE;
|
||||||
|
@ -2253,7 +2268,7 @@ static DWORD widReset(WORD wDevID)
|
||||||
wwi = &WInDev[wDevID];
|
wwi = &WInDev[wDevID];
|
||||||
OSSpinLockLock(&wwi->lock);
|
OSSpinLockLock(&wwi->lock);
|
||||||
|
|
||||||
if (wwi->state == WINE_WS_CLOSED)
|
if (wwi->state == WINE_WS_CLOSED || wwi->state == WINE_WS_CLOSING)
|
||||||
{
|
{
|
||||||
WARN("Trying to reset a closed device.\n");
|
WARN("Trying to reset a closed device.\n");
|
||||||
ret = MMSYSERR_INVALHANDLE;
|
ret = MMSYSERR_INVALHANDLE;
|
||||||
|
@ -2441,6 +2456,9 @@ OSStatus CoreAudio_wiAudioUnitIOProc(void *inRefCon,
|
||||||
|
|
||||||
lpStorePtr = wwi->lpQueuePtr;
|
lpStorePtr = wwi->lpQueuePtr;
|
||||||
|
|
||||||
|
/* We might have been called while the waveIn device is being closed in
|
||||||
|
* widClose. We have to do nothing in that case. The check of wwi->state
|
||||||
|
* below ensures that. */
|
||||||
while (dataToStore > 0 && wwi->state == WINE_WS_PLAYING && lpStorePtr)
|
while (dataToStore > 0 && wwi->state == WINE_WS_PLAYING && lpStorePtr)
|
||||||
{
|
{
|
||||||
unsigned int room = lpStorePtr->dwBufferLength - lpStorePtr->dwBytesRecorded;
|
unsigned int room = lpStorePtr->dwBufferLength - lpStorePtr->dwBytesRecorded;
|
||||||
|
|
Loading…
Reference in New Issue