diff --git a/dlls/winecoreaudio.drv/audio.c b/dlls/winecoreaudio.drv/audio.c index fcd84db21c9..dec38323446 100644 --- a/dlls/winecoreaudio.drv/audio.c +++ b/dlls/winecoreaudio.drv/audio.c @@ -211,6 +211,7 @@ static HANDLE hThread = NULL; /* Track the thread we create so we can clean it u static CFMessagePortRef Port_SendToMessageThread; static void wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo); +static void wodHelper_NotifyDoneForList(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr); static void wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force); static void widHelper_NotifyCompletions(WINE_WAVEIN* wwi); @@ -1049,6 +1050,24 @@ static void wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo) } } +/* Send the "done" notification for each WAVEHDR in a list. The list must be + * free-standing. It should not be part of a device's queue. + * This function must be called with the WAVEOUT lock *not* held. Furthermore, + * it does not lock it, itself. That's because the callback to the application + * may prompt the application to operate on the device, and we don't want to + * deadlock. + */ +static void wodHelper_NotifyDoneForList(WINE_WAVEOUT* wwo, LPWAVEHDR lpWaveHdr) +{ + for ( ; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) + { + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE; + lpWaveHdr->dwFlags |= WHDR_DONE; + + wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0); + } +} + /* if force is TRUE then notify the client that all the headers were completed */ static void wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force) @@ -1097,13 +1116,7 @@ static void wodHelper_NotifyCompletions(WINE_WAVEOUT* wwo, BOOL force) OSSpinLockUnlock(&wwo->lock); /* Now, send the "done" notification for each header in our list. */ - for (lpWaveHdr = lpFirstDoneWaveHdr; lpWaveHdr; lpWaveHdr = lpWaveHdr->lpNext) - { - lpWaveHdr->dwFlags &= ~WHDR_INQUEUE; - lpWaveHdr->dwFlags |= WHDR_DONE; - - wodNotifyClient(wwo, WOM_DONE, (DWORD)lpWaveHdr, 0); - } + wodHelper_NotifyDoneForList(wwo, lpFirstDoneWaveHdr); }