File libmikmod-alsadrv.patch of Package libmikmod

drv_alsa: Fix stuttering sound and hang on exit

This patch addresses the following 2 issues:

1) With some apps using mikmod's alsa output would lead to stutering sound,
this is caused by setting incorrect swparams from the set_swparams function,
specifically by setting the start threshold to 0.

Since drv_alsa uses alsa_pcm_set_params which already sets sane defaults for
the swparams this patch simply drops the custom set_swparams function.

2) Apps using mikmod's alsa output would hang on exit in snd_pcm_drain because
ALSA_PlayStop would call snd_pcm_pause causing the snd_pcm_drain on exit to
never complete. This patch modifies ALSA_PlayStop to use snd_pcm_drop instead.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
--- libmikmod-3.2.0/drivers/drv_alsa.c	2012-06-01 15:05:53.000000000 +0200
+++ libmikmod-3.2.0.new/drivers/drv_alsa.c	2013-04-06 12:23:24.260062259 +0200
@@ -108,7 +108,7 @@
 #ifdef OLD_ALSA
 static int(*alsa_pcm_flush_playback)(snd_pcm_t*);
 #else
-static int(*alsa_pcm_pause)(snd_pcm_t*, int);
+static int(*alsa_pcm_drop)(snd_pcm_t*);
 #endif
 #ifdef OLD_ALSA
 static int(*alsa_pcm_open)(snd_pcm_t**,int,int,int);
@@ -169,7 +169,7 @@
 #ifdef OLD_ALSA
 #define alsa_pcm_flush_playback		snd_pcm_flush_playback
 #else
-#define alsa_pcm_pause		snd_pcm_pause
+#define alsa_pcm_drop				snd_pcm_drop
 #endif
 #define alsa_pcm_open				snd_pcm_open
 #ifdef OLD_ALSA
@@ -199,7 +199,6 @@
 static	int cardmin=0,cardmax=SND_CARDS;
 #else
 static snd_pcm_sframes_t period_size;
-static snd_pcm_sframes_t buffer_size_in_frames;
 static int bytes_written = 0, bytes_played = 0;
 #endif
 static int global_frame_size;
@@ -252,7 +251,7 @@
 #ifdef OLD_ALSA
 	if(!(alsa_pcm_flush_playback   =dlsym(libasound,"snd_pcm_flush_playback"))) return 1;
 #else
-	if(!(alsa_pcm_pause   =dlsym(libasound,"snd_pcm_pause"))) return 1;
+	if (!(alsa_pcm_drop = dlsym(libasound, "snd_pcm_drop"))) return 1;
 #endif
 	if(!(alsa_pcm_open             =dlsym(libasound,"snd_pcm_open"))) return 1;
 #ifdef OLD_ALSA
@@ -311,7 +310,7 @@
 #ifdef OLD_ALSA
 	alsa_pcm_flush_playback   =NULL;
 #else
-	alsa_pcm_pause   =NULL;
+	alsa_pcm_drop = NULL;
 #endif
 	alsa_pcm_open             =NULL;
 #ifdef OLD_ALSA
@@ -392,41 +391,6 @@
 	return retval;
 }
 
-#ifndef OLD_ALSA
-static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
-{
-	int err;
-
-	/* get the current swparams */
-	err = alsa_pcm_sw_params_current(handle, swparams);
-	if (err < 0) {
-		printf("Unable to determine current swparams for playback: %s\n", alsa_strerror(err));
-		return err;
-	}
-	/* start the transfer when the buffer is almost full: */
-	/* (buffer_size / avail_min) * avail_min */
-	err = alsa_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size_in_frames / period_size) * period_size);
-	if (err < 0) {
-		printf("Unable to set start threshold mode for playback: %s\n", alsa_strerror(err));
-		return err;
-	}
-	/* allow the transfer when at least period_size samples can be processed */
-	/* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
-	err = alsa_pcm_sw_params_set_avail_min(handle, swparams, period_size);
-	if (err < 0) {
-		printf("Unable to set avail min for playback: %s\n", alsa_strerror(err));
-		return err;
-	}
-	/* write the parameters to the playback device */
-	err = alsa_pcm_sw_params(handle, swparams);
-	if (err < 0) {
-		printf("Unable to set sw params for playback: %s\n", alsa_strerror(err));
-		return err;
-	}
-	return 0;
-}
-#endif
-
 static BOOL ALSA_Init_internal(void)
 {
 	snd_pcm_format_t pformat;
@@ -648,23 +612,15 @@
                     printf("Unable to get buffer size for playback: %s\n", alsa_strerror(err));
                     goto END;
                 }
-                buffer_size_in_frames = 1200;
                 period_size = temp_u_period_size;
             }
-
-            /* The set_swparams function was taken from test/pcm.c
-             * in the alsa-lib distribution*/
-            if ((err = set_swparams(pcm_h, swparams)) < 0) {
-                printf("Setting of swparams failed: %s\n", snd_strerror(err));
-                goto END;
-            }
 #endif
 
 			if (!(audiobuffer=(SBYTE*)MikMod_malloc(
 #ifdef OLD_ALSA
                         fragmentsize
 #else
-                        buffer_size_in_frames * global_frame_size
+                        period_size * global_frame_size
 #endif
                         ))) {
 #ifdef OLD_ALSA
@@ -796,7 +752,8 @@
     {
         if (bytes_written == 0 || bytes_played == bytes_written)
         {
-            bytes_written = VC_WriteBytes(audiobuffer,buffer_size_in_frames * global_frame_size);
+            bytes_written = VC_WriteBytes(audiobuffer,
+                                          period_size * global_frame_size);
             bytes_played = 0;
         }
 
@@ -827,7 +784,7 @@
 #ifdef OLD_ALSA
 	alsa_pcm_flush_playback(pcm_h);
 #else
-    alsa_pcm_pause(pcm_h, 1);
+	alsa_pcm_drop(pcm_h);
 #endif
 }
 
openSUSE Build Service is sponsored by