I have found that since a few weeks my Eudora was hanging with current Cvs when I tried to get a new message off the server. This occurred exactly when it was trying to play a sound to warn about the new message. I have found that playing any sound using PlaySound is triggering the new problem. On my older computer, the problem just does not exist. After investigation, the older computer has a true sound card (a sound blaster) while the new has just a Via chip on the mother board (via82cxx_audio) This is the reason : the Via wineoss driver seems to be buggy, when a sound is finished, the available space never goes back to the total available. This problem did not happen with versions of audio.c < 1.45, where the Wine code has been made to rely on this feature. ChangeLog: * dlls/winmm/wineoss/audio.c Works around a bug in Via wineoss driver
Index: dlls/winmm/wineoss/audio.c =================================================================== RCS file: /home/wine/wine/dlls/winmm/wineoss/audio.c,v retrieving revision 1.47 diff -u -r1.47 audio.c --- dlls/winmm/wineoss/audio.c 2001/11/19 02:10:50 1.47 +++ dlls/winmm/wineoss/audio.c 2001/12/03 12:48:35 @@ -131,6 +131,8 @@ DWORD dwPlayedTotal; /* number of bytes played since opening */ DWORD dwWrittenTotal; /* number of bytes written since opening */ + DWORD dwPreviousTotal; + int cntTotalChange; /* synchronization stuff */ HANDLE hStartUpEvent; @@ -646,6 +648,23 @@ } +/* works around buggy wineoss driver never finishing + update of played data :-//, that is, info.bytes + stays at a few hundred of bytes and never goes to 0 + when the end of sound data is hit. This hack avoids an + infinite notification loop and Wine hangging. +*/ +void workAroundBuggyWineOSSDriver( WINE_WAVEOUT* wwo) +{ + if (wwo->dwPlayedTotal == wwo->dwPreviousTotal) + wwo->cntTotalChange++; + else + wwo->cntTotalChange = 0; + wwo->dwPreviousTotal = wwo->dwPlayedTotal; + if ((!wwo->lpPlayPtr) && (wwo->cntTotalChange > 2) && (wwo->lpQueuePtr)) + wwo->lpQueuePtr->reserved = wwo->dwPlayedTotal; /* force exit */ +} + /************************************************************************** * wodPlayer_NotifyCompletions [internal] * @@ -659,6 +678,8 @@ LPWAVEHDR lpWaveHdr; updatePlayedTotal(wwo); + workAroundBuggyWineOSSDriver(wwo); + /* Start from lpQueuePtr and keep notifying until: * - we hit an unwritten wavehdr * - we hit the beginning of a running loop @@ -717,7 +738,10 @@ wwo->state = WINE_WS_STOPPED; wwo->dwPlayedTotal = 0; wwo->dwWrittenTotal = 0; - } else { + wwo->dwPreviousTotal = 0; + wwo->cntTotalChange = 0; + } + else { /* FIXME: this is not accurate when looping, but can be do better ? */ wwo->lpPlayPtr = (wwo->lpLoopPtr) ? wwo->lpLoopPtr : wwo->lpQueuePtr; wwo->state = WINE_WS_PAUSED;