| Switch madplay to the new API. This is done thanks to a patch written |
| by Micha Nelissen <micha@neli.hopto.org> and available at |
| http://article.gmane.org/gmane.comp.audio.mad.devel/729. |
| |
| --- madplay-0.15.2b/audio_alsa.c 2008-10-18 15:10:16.000000000 +0200 |
| +++ madplay-0.15.2b/audio_alsa.c.new 2008-10-18 15:03:27.000000000 +0200 |
| @@ -28,31 +28,30 @@ |
| |
| #include <errno.h> |
| |
| -#define ALSA_PCM_OLD_HW_PARAMS_API |
| -#define ALSA_PCM_OLD_SW_PARAMS_API |
| #include <alsa/asoundlib.h> |
| |
| #include <mad.h> |
| |
| #include "audio.h" |
| |
| -char *buf = NULL; |
| -int paused = 0; |
| +#define BUFFER_TIME_MAX 500000 |
| |
| -int rate = -1; |
| -int channels = -1; |
| -int bitdepth = -1; |
| -int sample_size = -1; |
| - |
| -int buffer_time = 500000; |
| -int period_time = 100000; |
| -char *defaultdev = "plughw:0,0"; |
| +unsigned char *buf = NULL; |
| +int paused = 0; |
| + |
| +unsigned int rate = 0; |
| +unsigned int channels = -1; |
| +unsigned int bitdepth = -1; |
| +unsigned int sample_size = -1; |
| + |
| +unsigned int buffer_time; |
| +unsigned int period_time; |
| +char *defaultdev = "plughw:0,0"; |
| |
| snd_pcm_hw_params_t *alsa_hwparams; |
| snd_pcm_sw_params_t *alsa_swparams; |
| |
| -snd_pcm_sframes_t buffer_size; |
| -snd_pcm_sframes_t period_size; |
| +snd_pcm_uframes_t buffer_size; |
| |
| snd_pcm_format_t alsa_format = -1; |
| snd_pcm_access_t alsa_access = SND_PCM_ACCESS_MMAP_INTERLEAVED; |
| @@ -66,14 +65,20 @@ |
| snd_pcm_hw_params_t *params, |
| snd_pcm_access_t access) |
| { |
| - int err, dir; |
| - |
| + int err; |
| + |
| /* choose all parameters */ |
| err = snd_pcm_hw_params_any(handle,params); |
| if (err < 0) { |
| printf("Access type not available for playback: %s\n", snd_strerror(err)); |
| return err; |
| } |
| + /* set the access type */ |
| + err = snd_pcm_hw_params_set_access(handle, params, alsa_access); |
| + if (err < 0) { |
| + printf("Sample format not available for playback: %s\n", snd_strerror(err)); |
| + return err; |
| + } |
| /* set the sample format */ |
| err = snd_pcm_hw_params_set_format(handle, params, alsa_format); |
| if (err < 0) { |
| @@ -87,29 +92,38 @@ |
| return err; |
| } |
| /* set the stream rate */ |
| - err = snd_pcm_hw_params_set_rate_near(handle, params, rate, 0); |
| + err = snd_pcm_hw_params_set_rate(handle, params, rate, 0); |
| if (err < 0) { |
| printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); |
| return err; |
| } |
| - if (err != rate) { |
| - printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err); |
| - return -EINVAL; |
| - } |
| + err = snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, NULL); |
| + if (err < 0) { |
| + printf("Unable to retrieve buffer time: %s\n", snd_strerror(err)); |
| + return err; |
| + } |
| + if (buffer_time > BUFFER_TIME_MAX) |
| + buffer_time = BUFFER_TIME_MAX; |
| /* set buffer time */ |
| - err = snd_pcm_hw_params_set_buffer_time_near(handle, params, buffer_time, &dir); |
| + err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0); |
| if (err < 0) { |
| printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err)); |
| return err; |
| } |
| - buffer_size = snd_pcm_hw_params_get_buffer_size(params); |
| + if (period_time * 4 > buffer_time) |
| + period_time = buffer_time / 4; |
| /* set period time */ |
| - err = snd_pcm_hw_params_set_period_time_near(handle, params, period_time, &dir); |
| + err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, NULL); |
| if (err < 0) { |
| printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err)); |
| return err; |
| } |
| - period_size = snd_pcm_hw_params_get_period_size(params, &dir); |
| + /* retrieve buffer size */ |
| + err = snd_pcm_hw_params_get_buffer_size(params, &buffer_size); |
| + if (err < 0) { |
| + printf("Unable to retrieve buffer size: %s\n", snd_strerror(err)); |
| + return err; |
| + } |
| /* write the parameters to device */ |
| err = snd_pcm_hw_params(handle, params); |
| if (err < 0) { |
| @@ -123,6 +137,7 @@ |
| int set_swparams(snd_pcm_t *handle, |
| snd_pcm_sw_params_t *params) |
| { |
| + unsigned int start_threshold; |
| int err; |
| |
| /* get current swparams */ |
| @@ -136,13 +151,7 @@ |
| if (err < 0) { |
| printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err)); |
| return err; |
| - } |
| - /* allow transfer when at least period_size samples can be processed */ |
| - err = snd_pcm_sw_params_set_avail_min(handle, params, period_size); |
| - if (err < 0) { |
| - printf("Unable to set avail min for playback: %s\n", snd_strerror(err)); |
| - return err; |
| - } |
| + } |
| /* align all transfers to 1 samples */ |
| err = snd_pcm_sw_params_set_xfer_align(handle, params, 1); |
| if (err < 0) { |
| @@ -190,7 +199,7 @@ |
| rate = config->speed; |
| |
| if ( bitdepth == 0 ) |
| - config->precision = bitdepth = 32; |
| + config->precision = bitdepth = 16; |
| |
| switch (bitdepth) |
| { |
| @@ -241,7 +250,7 @@ |
| return -1; |
| } |
| |
| - buf = malloc(buffer_size); |
| + buf = malloc(buffer_size * sample_size); |
| if (buf == NULL) { |
| audio_error="unable to allocate output buffer table"; |
| return -1; |
| @@ -279,7 +288,7 @@ |
| int play(struct audio_play *play) |
| { |
| int err, len; |
| - char *ptr; |
| + unsigned char *ptr; |
| |
| ptr = buf; |
| len = play->nsamples; |
| |