[libmikmod] Fix stuttering sound and hang on exit for apps using libmikmod's alsa driver

Hans de Goede jwrdegoede at fedoraproject.org
Sat Apr 6 12:02:23 UTC 2013


commit 479d52a35e65a839d41a40807f7c3af9f31d8ab9
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Apr 6 14:06:17 2013 +0200

    Fix stuttering sound and hang on exit for apps using libmikmod's alsa driver
    
    - Remove non standard options configure adds to CFLAGS
    - Run autoreconf for aarch64 support (rhbz#925794)

 libmikmod-alsadrv.patch |  148 +++++++++++++++++++++++++++++++++++++++++++++++
 libmikmod-cflags.patch  |   71 ++++++++++++++++++++++
 libmikmod.spec          |   14 ++++-
 3 files changed, 231 insertions(+), 2 deletions(-)
---
diff --git a/libmikmod-alsadrv.patch b/libmikmod-alsadrv.patch
new file mode 100644
index 0000000..da3f4fa
--- /dev/null
+++ b/libmikmod-alsadrv.patch
@@ -0,0 +1,148 @@
+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 at 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
+ }
+ 
diff --git a/libmikmod-cflags.patch b/libmikmod-cflags.patch
new file mode 100644
index 0000000..fbe6349
--- /dev/null
+++ b/libmikmod-cflags.patch
@@ -0,0 +1,71 @@
+diff -up libmikmod-3.2.0/config.h.in~ libmikmod-3.2.0/config.h.in
+diff -up libmikmod-3.2.0/configure.in~ libmikmod-3.2.0/configure.in
+--- libmikmod-3.2.0/configure.in~	2012-06-01 15:15:29.000000000 +0200
++++ libmikmod-3.2.0/configure.in	2013-04-06 12:43:30.200076725 +0200
+@@ -634,66 +634,6 @@ then
+ 	fi
+ fi
+ 
+-# If compiling with gcc, use adequate optimization flags
+-if test $ac_cv_prog_gcc = yes
+-then
+-	# On at least x86 platforms, gcc 2.7.2.1 and earlier won't work if -O3 (or
+-	# -finline-functions) are used. Versions 2.7.2.3, 2.8.x and egcs are ok
+-	# (didn't test 2.7.2.2).
+-	# Until there's an easy way to catch broken inlining, we choose flags known
+-	# to work correctly depending of the compiler version.
+-	AC_CACHE_CHECK([if inlining functions is safe],
+-	libmikmod_cv_gcc_inline_safe,
+-	AC_TRY_RUN([
+-int main()
+-{
+-#if defined __GNUC__ && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ > 7)
+-	exit(0);
+-#else
+-	exit(1);
+-#endif
+-}],
+-	libmikmod_cv_gcc_inline_safe=yes,
+-	libmikmod_cv_gcc_inline_safe=no,
+-	libmikmod_cv_gcc_inline_safe=no))
+-	if test $libmikmod_cv_gcc_inline_safe = yes
+-	then
+-		CFLAGS="$CFLAGS -finline-functions"
+-	else
+-		CFLAGS="$CFLAGS -fno-strength-reduce"
+-	fi
+-	CFLAGS="$CFLAGS -funroll-loops -ffast-math"
+-	if test $libmikmod_debug = yes
+-	then
+-		CFLAGS="$CFLAGS -Wall -Werror"
+-	else
+-		CFLAGS="$CFLAGS -Wall"
+-	fi
+-
+-	# pgcc 2.95.2 appears not to be able to compile libmikmod, although regular
+-	# gcc works fine. Issue a warning if the compiler is pgcc, until a reliable
+-	# way to detect flawed version (or, better, a reliable workaround) is
+-	# found.
+-dnl do not cache this test - better rechecking every time
+-	AC_MSG_CHECKING(if compiler is pgcc)
+-	if ($CC -v 2>&1 | grep ^pgcc > /dev/null) 2>/dev/null
+-	then
+-		libmikmod_gcc_is_pgcc=yes
+-	else
+-		libmikmod_gcc_is_pgcc=no
+-	fi
+-	AC_MSG_RESULT($libmikmod_gcc_is_pgcc)
+-	if test $libmikmod_gcc_is_pgcc = yes
+-	then
+-		echo "
+-*** Version 2.95.2 of this compiler, and perhaps others, are unable to
+-*** compile libmikmod. If compilation fails for playercode/virtch.c
+-*** around line 650, with the error ``internal error--insn does not
+-*** satisfy its constraints'', then you'll have to use another compiler.
+-" >&2
+-	fi
+-fi
+-
+ if test x$libmikmod_threads != xno
+ then
+ 	AC_DEFINE(HAVE_PTHREAD)
diff --git a/libmikmod.spec b/libmikmod.spec
index 93d2692..d7f8235 100644
--- a/libmikmod.spec
+++ b/libmikmod.spec
@@ -1,7 +1,7 @@
 Summary:        A MOD music file player library
 Name:           libmikmod
 Version:        3.2.0
-Release:        20%{?dist}
+Release:        21%{?dist}
 License:        GPLv2 and LGPLv2+
 Group:          Applications/Multimedia
 URL:            http://mikmod.shlomifish.org/
@@ -13,7 +13,9 @@ Patch3:         libmikmod-CVE-2007-6720.patch
 Patch4:         libmikmod-CVE-2009-0179.patch
 # Fix rhbz#855130
 Patch5:         libmikmod-malloc-fail.patch
-BuildRequires:  alsa-lib-devel
+Patch6:         libmikmod-alsadrv.patch
+Patch7:         libmikmod-cflags.patch
+BuildRequires:  alsa-lib-devel libtool
 
 %description
 libmikmod is a library used by the mikmod MOD music file player for
@@ -42,6 +44,9 @@ applications for mikmod.
 %patch3 -p1
 %patch4 -p1
 %patch5 -p1
+%patch6 -p1
+%patch7 -p1
+autoreconf -i -f
 
 
 %build
@@ -83,6 +88,11 @@ fi
 
 
 %changelog
+* Sat Apr  6 2013 Hans de Goede <hdegoede at redhat.com> - 3.2.0-21
+- Fix stuttering sound and hang on exit for apps using libmikmod's alsa driver
+- Remove non standard options configure adds to CFLAGS
+- Run autoreconf for aarch64 support (rhbz#925794)
+
 * Thu Feb 14 2013 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 3.2.0-20
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
 


More information about the scm-commits mailing list