diff -ruN mpg123-0.59r.orig/audio.c mpg123-0.59r/audio.c --- mpg123-0.59r.orig/audio.c Wed Apr 7 00:53:05 1999 +++ mpg123-0.59r/audio.c Wed May 10 16:13:12 2000 @@ -19,7 +19,8 @@ ai->handle = NULL; ai->alsa_format.format = -1; ai->alsa_format.rate = -1; - ai->alsa_format.channels = -1; + ai->alsa_format.voices = -1; + ai->buf = NULL; #endif ai->device = NULL; ai->channels = -1; diff -ruN mpg123-0.59r.orig/audio.h mpg123-0.59r/audio.h --- mpg123-0.59r.orig/audio.h Wed Jun 16 05:22:03 1999 +++ mpg123-0.59r/audio.h Wed May 10 16:13:12 2000 @@ -53,8 +53,9 @@ long gain; int output; #ifdef ALSA - void *handle; + snd_pcm_t *handle; snd_pcm_format_t alsa_format; + unsigned char *buf; #endif char *device; int channels; Binary files mpg123-0.59r.orig/audio.o and mpg123-0.59r/audio.o differ diff -ruN mpg123-0.59r.orig/audio_alsa.c mpg123-0.59r/audio_alsa.c --- mpg123-0.59r.orig/audio_alsa.c Fri May 28 19:25:50 1999 +++ mpg123-0.59r/audio_alsa.c Fri May 12 20:38:12 2000 @@ -4,6 +4,7 @@ * Code by Anders Semb Hermansen * Cleanups by Jaroslav Kysela * Ville Syrjala + * ALSA 0.[56] support by katsuhiro Ueno * * You can use -a :... * For example: mpg123 -a 1:0 aaa.mpg @@ -72,33 +73,107 @@ return -1; } + if (ai->buf) + free(ai->buf); + ai->buf = NULL; + return 0; } static void audio_set_playback_params(struct audio_info_struct *ai) { int err; - snd_pcm_playback_info_t pi; - snd_pcm_playback_params_t pp; - - if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 ) + snd_pcm_channel_info_t ci; + snd_pcm_channel_params_t cp; + snd_pcm_channel_setup_t setup; + + if(ai->alsa_format.rate == -1 + || ai->alsa_format.format == -1 + || ai->alsa_format.voices == -1) + return; + + memset(&ci, 0, sizeof(ci)); + ci.channel = SND_PCM_CHANNEL_PLAYBACK; + if((err=snd_pcm_channel_info(ai->handle, &ci)) < 0 ) { - fprintf(stderr, "playback info failed: %s\n", snd_strerror(err)); + fprintf(stderr, "snd_pcm_channel_info failed: %s\n", snd_strerror(err)); return; /* not fatal error */ } - bzero(&pp, sizeof(pp)); - pp.fragment_size = pi.buffer_size/4; - if (pp.fragment_size > pi.max_fragment_size) pp.fragment_size = pi.max_fragment_size; - if (pp.fragment_size < pi.min_fragment_size) pp.fragment_size = pi.min_fragment_size; - pp.fragments_max = -1; - pp.fragments_room = 1; + snd_pcm_channel_flush(ai->handle, SND_PCM_CHANNEL_PLAYBACK); + + if(ai->alsa_format.rate < ci.min_rate + || ci.max_rate < ai->alsa_format.rate) { + fprintf(stderr, "unsupported rate %dHz\n", ai->alsa_format.rate); + return; + } + if(ai->alsa_format.voices < ci.min_voices + || ci.max_voices < ai->alsa_format.voices) { + fprintf(stderr, "unsupported voice %d\n", ai->alsa_format.voices); + return; + } + if(!(ci.formats & (1 << ai->alsa_format.format))) { + fprintf(stderr, "unsupported format\n"); + return; + } + + memset(&cp, 0, sizeof(cp)); + cp.mode = SND_PCM_MODE_BLOCK; + cp.channel = SND_PCM_CHANNEL_PLAYBACK; + cp.start_mode = SND_PCM_START_FULL; +#if SND_LIB_MINOR >= 6 + cp.xrun_mode = SND_PCM_XRUN_FLUSH; +#else + cp.stop_mode = SND_PCM_STOP_STOP; +#endif + cp.format.interleave = 1; + cp.format.format = ai->alsa_format.format; + cp.format.rate = ai->alsa_format.rate; + cp.format.voices = ai->alsa_format.voices; + +#if SND_LIB_MINOR >= 6 + cp.frag_size = audiobufsize; + cp.buffer_size = ci.buffer_size; + cp.buf.block.frags_xrun_max = 0; + cp.buf.block.frags_min = 1; +#else + cp.buf.block.frag_size = audiobufsize; + cp.buf.block.frags_max = -1; + cp.buf.block.frags_min = 1; +#endif + + if((err=snd_pcm_channel_params(ai->handle, &cp)) < 0 ) + { + fprintf(stderr, "snd_pcm_channel_params failed: %s\n", snd_strerror(err)); + return; /* not fatal error */ + } + + if((err=snd_pcm_channel_prepare(ai->handle, SND_PCM_CHANNEL_PLAYBACK)) < 0 ) + { + fprintf(stderr, "snd_pcm_channel_prepare failed: %s\n", snd_strerror(err)); + return; /* not fatal error */ + } - if((err=snd_pcm_playback_params(ai->handle, &pp)) < 0 ) + memset(&setup, 0, sizeof(setup)); + setup.channel = SND_PCM_CHANNEL_PLAYBACK; + if((err=snd_pcm_channel_setup(ai->handle, &setup)) < 0 ) { - fprintf(stderr, "playback params failed: %s\n", snd_strerror(err)); + fprintf(stderr, "snd_pcm_channel_setup failed: %s\n", snd_strerror(err)); return; /* not fatal error */ } + if (setup.format.format != ai->alsa_format.format + || setup.format.rate != ai->alsa_format.rate + || setup.format.voices != ai->alsa_format.voices +#if SND_LIB_MINOR >= 6 + || setup.frag_size != audiobufsize +#else + || setup.buf.block.frag_size != audiobufsize +#endif + ) + { + fprintf(stderr, "format not supported.\n"); + return; + } } int audio_reset_parameters(struct audio_info_struct *ai) @@ -107,6 +182,7 @@ audio_set_channels(ai); audio_set_rate(ai); + audio_set_playback_params(ai); return 0; } @@ -117,42 +193,24 @@ int audio_set_rate(struct audio_info_struct *ai) { - int ret; - if(!ai || ai->rate < 0) return -1; ai->alsa_format.rate=ai->rate; - - if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 ) - return -1; - - audio_set_playback_params(ai); - return 0; } int audio_set_channels(struct audio_info_struct *ai) { - int ret; - - if(ai->alsa_format.channels < 0) + if(ai->channels < 0) return 0; - ai->alsa_format.channels = ai->channels; - - if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 ) - return -1; - - audio_set_playback_params(ai); - + ai->alsa_format.voices = ai->channels; return 0; } int audio_set_format(struct audio_info_struct *ai) { - int ret; - if(ai->format == -1) return 0; @@ -179,11 +237,6 @@ break; } - if((ret=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 ) - return -1; - - audio_set_playback_params(ai); - return 0; } @@ -191,7 +244,7 @@ { int i, err; int fmt = -1; - snd_pcm_playback_info_t pi; + snd_pcm_channel_info_t ci; static int fmts[] = { AUDIO_FORMAT_SIGNED_16, AUDIO_FORMAT_UNSIGNED_16, @@ -204,14 +257,16 @@ SND_PCM_FMT_MU_LAW, SND_PCM_FMT_A_LAW }; - if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 ) + memset(&ci, 0, sizeof(ci)); + ci.channel = SND_PCM_CHANNEL_PLAYBACK; + if((err=snd_pcm_channel_info(ai->handle, &ci)) < 0 ) { - fprintf(stderr, "playback info failed: %s\n", snd_strerror(err)); + fprintf(stderr, "snd_pcm_channel_info failed: %s\n", snd_strerror(err)); return -1; } for (i = 0; i < 6; i++) { - if (pi.formats & afmts[i]) { + if (ci.formats & afmts[i]) { if (fmt == -1) fmt = 0; fmt |= fmts[i]; @@ -223,16 +278,57 @@ int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len) { - ssize_t ret; + int n; + snd_pcm_channel_status_t cs; + + if (len < audiobufsize) { + if (!ai->buf) { + ai->buf = malloc(audiobufsize); + if (!ai->buf) + return -1; + } + memcpy(ai->buf, buf, len); +#if SND_LIB_MINOR >= 6 + snd_pcm_format_set_silence(ai->alsa_format.format, + ai->buf + len, audiobufsize - len); +#else + memset(ai->buf + len, 0, audiobufsize - len); +#endif + buf = ai->buf; + } - ret=snd_pcm_write(ai->handle, buf, len); + n = snd_pcm_write(ai->handle, buf, audiobufsize); - return ret; + if (n != audiobufsize) { + memset(&cs, 0, sizeof(cs)); + cs.channel = SND_PCM_CHANNEL_PLAYBACK; + snd_pcm_channel_status(ai->handle, &cs); +#if SND_LIB_MINOR >= 6 + if (cs.status != SND_PCM_STATUS_XRUN) +#else + if (cs.status != SND_PCM_STATUS_UNDERRUN) +#endif + return -1; + snd_pcm_channel_flush(ai->handle, SND_PCM_CHANNEL_PLAYBACK); + snd_pcm_channel_prepare(ai->handle, SND_PCM_CHANNEL_PLAYBACK); + n = snd_pcm_write(ai->handle, buf, audiobufsize); + if (n != audiobufsize) { + fprintf(stderr, "snd_pcm_write: %s", snd_strerror(n)); + return -1; + } + } + + return len; } int audio_close(struct audio_info_struct *ai) { int ret; + + if (ai->buf) + free(ai->buf); + + snd_pcm_channel_flush(ai->handle, SND_PCM_CHANNEL_PLAYBACK); ret = snd_pcm_close(ai->handle); return ret; } diff -ruN mpg123-0.59r.orig/mpg123.h mpg123-0.59r/mpg123.h --- mpg123-0.59r.orig/mpg123.h Fri May 28 23:51:58 1999 +++ mpg123-0.59r/mpg123.h Fri May 12 20:34:52 2000 @@ -53,11 +53,11 @@ #endif #ifdef REAL_IS_FLOAT -# define real float +typedef float real; #elif defined(REAL_IS_LONG_DOUBLE) -# define real long double +typedef long double real; #else -# define real double +typedef double real; #endif #ifdef __GNUC__