Commit 13a7708a authored by Andrew Nguyen's avatar Andrew Nguyen Committed by Alexandre Julliard

winealsa.drv: Replicate the snd_pcm_recover alsa-lib implementation to cope with…

winealsa.drv: Replicate the snd_pcm_recover alsa-lib implementation to cope with older alsa-lib versions.
parent dd12cf71
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Wine Driver for ALSA * Wine Driver for ALSA
* *
* Copyright 2002 Eric Pouech * Copyright 2002 Eric Pouech
* Copyright 2006 Jaroslav Kysela
* Copyright 2007 Maarten Lankhorst * Copyright 2007 Maarten Lankhorst
* *
* This file has a few shared generic subroutines shared among the alsa * This file has a few shared generic subroutines shared among the alsa
...@@ -556,24 +557,42 @@ out: ...@@ -556,24 +557,42 @@ out:
/************************************************************************** /**************************************************************************
* ALSA_XRUNRecovery [internal] * wine_snd_pcm_recover [internal]
* *
* used to recovery from XRUN errors (buffer underflow/overflow) * Code slightly modified from alsa-lib v1.0.23 snd_pcm_recover implementation.
* used to recover from XRUN errors (buffer underflow/overflow)
*/ */
int ALSA_XRUNRecovery(WINE_WAVEDEV * wwo, int err) int wine_snd_pcm_recover(snd_pcm_t *pcm, int err, int silent)
{ {
if (err == -EPIPE) { /* under-run */ if (err > 0)
err = snd_pcm_prepare(wwo->pcm); err = -err;
if (err < 0) if (err == -EINTR) /* nothing to do, continue */
ERR( "underrun recovery failed. prepare failed: %s\n", snd_strerror(err));
return 0; return 0;
} else if (err == -ESTRPIPE) { if (err == -EPIPE) {
while ((err = snd_pcm_resume(wwo->pcm)) == -EAGAIN) const char *s;
sleep(1); /* wait until the suspend flag is released */ if (snd_pcm_stream(pcm) == SND_PCM_STREAM_PLAYBACK)
s = "underrun";
else
s = "overrun";
if (!silent)
ERR("%s occurred", s);
err = snd_pcm_prepare(pcm);
if (err < 0) {
ERR("cannot recover from %s, prepare failed: %s", s, snd_strerror(err));
return err;
}
return 0;
}
if (err == -ESTRPIPE) {
while ((err = snd_pcm_resume(pcm)) == -EAGAIN)
/* wait until suspend flag is released */
poll(NULL, 0, 1000);
if (err < 0) { if (err < 0) {
err = snd_pcm_prepare(wwo->pcm); err = snd_pcm_prepare(pcm);
if (err < 0) if (err < 0) {
ERR("recovery from suspend failed, prepare failed: %s\n", snd_strerror(err)); ERR("cannot recover from suspend, prepare failed: %s", snd_strerror(err));
return err;
}
} }
return 0; return 0;
} }
......
...@@ -187,7 +187,7 @@ const char * ALSA_getFormat(WORD wFormatTag); ...@@ -187,7 +187,7 @@ const char * ALSA_getFormat(WORD wFormatTag);
BOOL ALSA_NearMatch(int rate1, int rate2); BOOL ALSA_NearMatch(int rate1, int rate2);
DWORD ALSA_bytes_to_mmtime(LPMMTIME lpTime, DWORD position, WAVEFORMATPCMEX* format); DWORD ALSA_bytes_to_mmtime(LPMMTIME lpTime, DWORD position, WAVEFORMATPCMEX* format);
void ALSA_TraceParameters(snd_pcm_hw_params_t * hw_params, snd_pcm_sw_params_t * sw, int full); void ALSA_TraceParameters(snd_pcm_hw_params_t * hw_params, snd_pcm_sw_params_t * sw, int full);
int ALSA_XRUNRecovery(WINE_WAVEDEV * wwo, int err); int wine_snd_pcm_recover(snd_pcm_t *pcm, int err, int silent);
void ALSA_copyFormat(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2); void ALSA_copyFormat(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2);
BOOL ALSA_supportedFormat(LPWAVEFORMATEX wf); BOOL ALSA_supportedFormat(LPWAVEFORMATEX wf);
......
...@@ -406,7 +406,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface, ...@@ -406,7 +406,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface,
if (ret == -EPIPE) if (ret == -EPIPE)
{ {
WARN("Underrun occurred\n"); WARN("Underrun occurred\n");
snd_pcm_recover(This->pcm, -EPIPE, 1); wine_snd_pcm_recover(This->pcm, -EPIPE, 1);
ret = snd_pcm_writei(This->pcm, pvAudio1, writelen); ret = snd_pcm_writei(This->pcm, pvAudio1, writelen);
/* Advance mmap pointer a little to make dsound notice the underrun and respond to it */ /* Advance mmap pointer a little to make dsound notice the underrun and respond to it */
......
...@@ -110,7 +110,7 @@ static BOOL wodUpdatePlayedTotal(WINE_WAVEDEV* wwo, snd_pcm_status_t* ps) ...@@ -110,7 +110,7 @@ static BOOL wodUpdatePlayedTotal(WINE_WAVEDEV* wwo, snd_pcm_status_t* ps)
if (state != SND_PCM_STATE_RUNNING && state != SND_PCM_STATE_PREPARED) if (state != SND_PCM_STATE_RUNNING && state != SND_PCM_STATE_PREPARED)
{ {
WARN("Unexpected state (%d) while updating Total Played, resetting\n", state); WARN("Unexpected state (%d) while updating Total Played, resetting\n", state);
snd_pcm_recover(wwo->pcm, -EPIPE, 0); wine_snd_pcm_recover(wwo->pcm, -EPIPE, 0);
delay=0; delay=0;
} }
...@@ -244,7 +244,7 @@ static int wodPlayer_WriteMaxFrags(WINE_WAVEDEV* wwo, DWORD* frames) ...@@ -244,7 +244,7 @@ static int wodPlayer_WriteMaxFrags(WINE_WAVEDEV* wwo, DWORD* frames)
written = (wwo->write)(wwo->pcm, lpWaveHdr->lpData + wwo->dwPartialOffset, toWrite); written = (wwo->write)(wwo->pcm, lpWaveHdr->lpData + wwo->dwPartialOffset, toWrite);
if ( written < 0) { if ( written < 0) {
/* XRUN occurred. let's try to recover */ /* XRUN occurred. let's try to recover */
ALSA_XRUNRecovery(wwo, written); wine_snd_pcm_recover(wwo->pcm, written, 0);
written = (wwo->write)(wwo->pcm, lpWaveHdr->lpData + wwo->dwPartialOffset, toWrite); written = (wwo->write)(wwo->pcm, lpWaveHdr->lpData + wwo->dwPartialOffset, toWrite);
} }
if (written <= 0) { if (written <= 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment