configure.ac: when checking for ALSA, look for snd_pcm_recover() instead of snd_pcm_hw_params_get_access()

Andrew Nguyen arethusa26 at gmail.com
Fri Jun 11 03:18:48 CDT 2010


On Sun, Jun 6, 2010 at 4:03 PM, Maarten Lankhorst
<m.b.lankhorst at gmail.com> wrote:
> Is snd_pcm_recover the only function missing? If so change it to dlsym, and
> add a copy of snd_pcm_recover to wine if it cannot find the libalsa one..

Is it a problem to eschew the use of dlsym? It feels like modifying
winealsa.drv to dynamically load libasound correctly would be much
more burdensome than simply replicating the snd_pcm_recover
implementation. I have a provisional patch that replaces a half-baked
snd_pcm_recover-like internal helper with the actual snd_pcm_recover
implementation from libasound. I would welcome any feedback on it.
-------------- next part --------------
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index 9eb50cd..af9547c 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -2,6 +2,7 @@
  * Wine Driver for ALSA
  *
  * Copyright	2002 Eric Pouech
+ * Copyright	2006 Jaroslav Kysela
  * Copyright	2007 Maarten Lankhorst
  *
  * This file has a few shared generic subroutines shared among the alsa
@@ -558,22 +559,40 @@ out:
 /**************************************************************************
  * 			ALSA_XRUNRecovery		[internal]
  *
- * used to recovery from XRUN errors (buffer underflow/overflow)
+ * Code copied 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 ALSA_XRUNRecovery(snd_pcm_t *pcm, int err, int silent)
 {
-    if (err == -EPIPE) {    /* under-run */
-        err = snd_pcm_prepare(wwo->pcm);
-        if (err < 0)
-             ERR( "underrun recovery failed. prepare failed: %s\n", snd_strerror(err));
+    if (err > 0)
+        err = -err;
+    if (err == -EINTR)	/* nothing to do, continue */
         return 0;
-    } else if (err == -ESTRPIPE) {
-        while ((err = snd_pcm_resume(wwo->pcm)) == -EAGAIN)
-            sleep(1);       /* wait until the suspend flag is released */
+    if (err == -EPIPE) {
+        const char *s;
+        if (snd_pcm_stream(pcm) == SND_PCM_STREAM_PLAYBACK)
+            s = "underrun";
+        else
+            s = "overrun";
+        if (!silent)
+            SNDERR("%s occured", s);
+        err = snd_pcm_prepare(pcm);
+        if (err < 0) {
+            SNDERR("cannot recovery 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) {
-            err = snd_pcm_prepare(wwo->pcm);
-            if (err < 0)
-                ERR("recovery from suspend failed, prepare failed: %s\n", snd_strerror(err));
+            err = snd_pcm_prepare(pcm);
+            if (err < 0) {
+                SNDERR("cannot recovery from suspend, prepare failed: %s", snd_strerror(err));
+                return err;
+            }
         }
         return 0;
     }
diff --git a/dlls/winealsa.drv/alsa.h b/dlls/winealsa.drv/alsa.h
index 7c2f0f4..5315b67 100644
--- a/dlls/winealsa.drv/alsa.h
+++ b/dlls/winealsa.drv/alsa.h
@@ -187,7 +187,7 @@ const char * ALSA_getFormat(WORD wFormatTag);
 BOOL	ALSA_NearMatch(int rate1, int rate2);
 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);
-int	ALSA_XRUNRecovery(WINE_WAVEDEV * wwo, int err);
+int	ALSA_XRUNRecovery(snd_pcm_t *pcm, int err, int silent);
 void	ALSA_copyFormat(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2);
 BOOL	ALSA_supportedFormat(LPWAVEFORMATEX wf);
 
diff --git a/dlls/winealsa.drv/dsoutput.c b/dlls/winealsa.drv/dsoutput.c
index bb81621..c4f32b0 100644
--- a/dlls/winealsa.drv/dsoutput.c
+++ b/dlls/winealsa.drv/dsoutput.c
@@ -406,7 +406,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface,
             if (ret == -EPIPE)
             {
                 WARN("Underrun occurred\n");
-                snd_pcm_recover(This->pcm, -EPIPE, 1);
+                ALSA_XRUNRecovery(This->pcm, -EPIPE, 1);
                 ret = snd_pcm_writei(This->pcm, pvAudio1, writelen);
 
                 /* Advance mmap pointer a little to make dsound notice the underrun and respond to it */
diff --git a/dlls/winealsa.drv/waveout.c b/dlls/winealsa.drv/waveout.c
index 4001f26..da5ba58 100644
--- a/dlls/winealsa.drv/waveout.c
+++ b/dlls/winealsa.drv/waveout.c
@@ -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)
     {
         WARN("Unexpected state (%d) while updating Total Played, resetting\n", state);
-        snd_pcm_recover(wwo->pcm, -EPIPE, 0);
+        ALSA_XRUNRecovery(wwo->pcm, -EPIPE, 0);
         delay=0;
     }
 
@@ -244,7 +244,7 @@ static int wodPlayer_WriteMaxFrags(WINE_WAVEDEV* wwo, DWORD* frames)
 	written = (wwo->write)(wwo->pcm, lpWaveHdr->lpData + wwo->dwPartialOffset, toWrite);
 	if ( written < 0) {
 	    /* XRUN occurred. let's try to recover */
-	    ALSA_XRUNRecovery(wwo, written);
+	    ALSA_XRUNRecovery(wwo->pcm, written, 0);
 	    written = (wwo->write)(wwo->pcm, lpWaveHdr->lpData + wwo->dwPartialOffset, toWrite);
 	}
 	if (written <= 0) {


More information about the wine-devel mailing list