More correct fix for dsp empty case.
This commit is contained in:
parent
bea24feaf8
commit
2db20ef1f0
|
@ -1297,13 +1297,32 @@ static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD
|
||||||
static BOOL wodUpdatePlayedTotal(WINE_WAVEOUT* wwo, audio_buf_info* info)
|
static BOOL wodUpdatePlayedTotal(WINE_WAVEOUT* wwo, audio_buf_info* info)
|
||||||
{
|
{
|
||||||
audio_buf_info dspspace;
|
audio_buf_info dspspace;
|
||||||
|
DWORD notplayed;
|
||||||
if (!info) info = &dspspace;
|
if (!info) info = &dspspace;
|
||||||
|
|
||||||
if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, info) < 0) {
|
if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, info) < 0) {
|
||||||
ERR("ioctl(%s, SNDCTL_DSP_GETOSPACE) failed (%s)\n", wwo->ossdev->dev_name, strerror(errno));
|
ERR("ioctl(%s, SNDCTL_DSP_GETOSPACE) failed (%s)\n", wwo->ossdev->dev_name, strerror(errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
wwo->dwPlayedTotal = wwo->dwWrittenTotal - (wwo->dwBufferSize - info->bytes);
|
|
||||||
|
/* GETOSPACE is not always accurate when we're down to the last fragment or two;
|
||||||
|
** we try to accomodate that here by assuming that the dsp is empty by looking
|
||||||
|
** at the clock rather than the result of GETOSPACE */
|
||||||
|
notplayed = wwo->dwBufferSize - info->bytes;
|
||||||
|
if (notplayed > 0 && notplayed < (info->fragsize * 2))
|
||||||
|
{
|
||||||
|
if (wwo->dwProjectedFinishTime && GetTickCount() >= wwo->dwProjectedFinishTime)
|
||||||
|
{
|
||||||
|
TRACE("Adjusting for a presumed OSS bug and assuming all data has been played.\n");
|
||||||
|
wwo->dwPlayedTotal = wwo->dwWrittenTotal;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Some OSS drivers will clean up nicely if given a POST, so give 'em the chance... */
|
||||||
|
ioctl(wwo->ossdev->fd, SNDCTL_DSP_POST, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
wwo->dwPlayedTotal = wwo->dwWrittenTotal - notplayed;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1370,6 +1389,16 @@ static LPWAVEHDR wodPlayer_PlayPtrNext(WINE_WAVEOUT* wwo)
|
||||||
return lpWaveHdr;
|
return lpWaveHdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* wodPlayer_TicksTillEmpty [internal]
|
||||||
|
* Returns the number of ticks until we think the DSP should be empty
|
||||||
|
*/
|
||||||
|
static DWORD wodPlayer_TicksTillEmpty(const WINE_WAVEOUT *wwo)
|
||||||
|
{
|
||||||
|
return ((wwo->dwWrittenTotal - wwo->dwPlayedTotal) * 1000)
|
||||||
|
/ wwo->waveFormat.Format.nAvgBytesPerSec;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* wodPlayer_DSPWait [internal]
|
* wodPlayer_DSPWait [internal]
|
||||||
* Returns the number of milliseconds to wait for the DSP buffer to write
|
* Returns the number of milliseconds to wait for the DSP buffer to write
|
||||||
|
@ -1659,17 +1688,6 @@ static DWORD wodPlayer_FeedDSP(WINE_WAVEOUT* wwo)
|
||||||
TRACE("fragments=%d/%d, fragsize=%d, bytes=%d\n",
|
TRACE("fragments=%d/%d, fragsize=%d, bytes=%d\n",
|
||||||
dspspace.fragments, dspspace.fragstotal, dspspace.fragsize, dspspace.bytes);
|
dspspace.fragments, dspspace.fragstotal, dspspace.fragsize, dspspace.bytes);
|
||||||
|
|
||||||
/* input queue empty and output buffer with less than one fragment to play
|
|
||||||
* actually some cards do not play the fragment before the last if this one is partially feed
|
|
||||||
* so we need to test for full the availability of 2 fragments ; the DSP_POST ioctl
|
|
||||||
* will let the card know to play out the rest of the fragments
|
|
||||||
*/
|
|
||||||
if (!wwo->lpPlayPtr && wwo->dwBufferSize < availInQ + 2 * wwo->dwFragmentSize &&
|
|
||||||
!wwo->bNeedPost) {
|
|
||||||
TRACE("Run out of wavehdr's, requesting a POST...\n");
|
|
||||||
wwo->bNeedPost = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no more room... no need to try to feed */
|
/* no more room... no need to try to feed */
|
||||||
if (dspspace.fragments != 0) {
|
if (dspspace.fragments != 0) {
|
||||||
/* Feed from partial wavehdr */
|
/* Feed from partial wavehdr */
|
||||||
|
@ -1724,6 +1742,11 @@ static DWORD CALLBACK wodPlayer(LPVOID pmt)
|
||||||
wodPlayer_ProcessMessages(wwo);
|
wodPlayer_ProcessMessages(wwo);
|
||||||
if (wwo->state == WINE_WS_PLAYING) {
|
if (wwo->state == WINE_WS_PLAYING) {
|
||||||
dwNextFeedTime = wodPlayer_FeedDSP(wwo);
|
dwNextFeedTime = wodPlayer_FeedDSP(wwo);
|
||||||
|
if (dwNextFeedTime != INFINITE)
|
||||||
|
wwo->dwProjectedFinishTime = GetTickCount() + wodPlayer_TicksTillEmpty(wwo);
|
||||||
|
else
|
||||||
|
wwo->dwProjectedFinishTime = 0;
|
||||||
|
|
||||||
dwNextNotifyTime = wodPlayer_NotifyCompletions(wwo, FALSE);
|
dwNextNotifyTime = wodPlayer_NotifyCompletions(wwo, FALSE);
|
||||||
if (dwNextFeedTime == INFINITE) {
|
if (dwNextFeedTime == INFINITE) {
|
||||||
/* FeedDSP ran out of data, but before flushing, */
|
/* FeedDSP ran out of data, but before flushing, */
|
||||||
|
|
|
@ -131,6 +131,10 @@ typedef struct {
|
||||||
HANDLE hThread;
|
HANDLE hThread;
|
||||||
DWORD dwThreadID;
|
DWORD dwThreadID;
|
||||||
OSS_MSG_RING msgRing;
|
OSS_MSG_RING msgRing;
|
||||||
|
|
||||||
|
/* make accomodation for the inacuraccy of OSS when reporting buffer size remaining by using the clock instead of GETOSPACE */
|
||||||
|
DWORD dwProjectedFinishTime;
|
||||||
|
|
||||||
} WINE_WAVEOUT;
|
} WINE_WAVEOUT;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
Loading…
Reference in New Issue