diff -ruN esound-0.2.8.orig/audio_alsa.c esound-0.2.8/audio_alsa.c --- esound-0.2.8.orig/audio_alsa.c Thu Dec 24 01:10:06 1998 +++ esound-0.2.8/audio_alsa.c Fri May 12 20:53:57 2000 @@ -9,6 +9,12 @@ # include #endif +#if defined(SND_LIB_MINOR) +#define ALSA_LIB SND_LIB_MINOR +#else +#define ALSA_LIB 3 +#endif + void *handle; /* so that EsounD can use other cards besides the first */ @@ -38,8 +44,13 @@ int esd_audio_open() { +#if ALSA_LIB >= 5 + snd_pcm_channel_params_t params; + snd_pcm_channel_setup_t setup; +#else snd_pcm_format_t format; snd_pcm_playback_params_t params; +#endif int ret, mode = SND_PCM_OPEN_PLAYBACK; int mask, card=ALSACARD, device=ALSADEVICE; char buf[256]; @@ -130,6 +141,85 @@ #endif /* set the sound driver audio format for playback */ +#if ALSA_LIB >= 5 + memset( ¶ms, 0, sizeof(params) ); + params.mode = SND_PCM_MODE_BLOCK; +#if ALSA_LIB >= 6 + params.xrun_mode = SND_PCM_XRUN_FLUSH; + params.frag_size = 4 * 1024; + params.buffer_size = 4 * 1024 * 2; + params.buf.block.frags_min = 1; + params.buf.block.frags_xrun_max = 0; +#else + params.stop_mode = SND_PCM_STOP_STOP; + params.buf.block.frag_size = 4*1024; + params.buf.block.frags_max = 2; + params.buf.block.frags_min = 1; +#endif + params.format.interleave = 1; + params.format.format = ( (esd_audio_format & ESD_MASK_BITS) == ESD_BITS16 ) + ? /* 16 bit */ SND_PCM_SFMT_S16_LE : /* 8 bit */ SND_PCM_SFMT_U8; + params.format.rate = esd_audio_rate; + params.format.voices = ( ( esd_audio_format & ESD_MASK_CHAN) == ESD_STEREO ) + ? 2 : 1; + if( mode == SND_PCM_OPEN_DUPLEX || mode == SND_PCM_OPEN_PLAYBACK) { + params.channel = SND_PCM_CHANNEL_PLAYBACK; + params.start_mode = SND_PCM_START_FULL; + if ( ( ret = snd_pcm_channel_params( handle, ¶ms ) ) < 0 ) { + fprintf( stderr, "set playback format failed: %s\n", snd_strerror( ret ) ); + esd_audio_close(); + esd_audio_fd = -1; + return ( -1 ); + } + if ( ( ret = snd_pcm_channel_prepare( handle, SND_PCM_CHANNEL_PLAYBACK ) ) < 0 ) { + fprintf( stderr, "prapare playback channel failed: %s\n", snd_strerror( ret ) ); + esd_audio_close(); + esd_audio_fd = -1; + return ( -1 ); + } + memset( &setup, 0, sizeof(setup) ); + setup.mode = SND_PCM_MODE_BLOCK; + setup.channel = SND_PCM_CHANNEL_PLAYBACK; + if ( ( ret = snd_pcm_channel_setup( handle, &setup ) ) < 0 ) { + fprintf( stderr, "setup playback channel failed: %s\n", snd_strerror( ret ) ); + esd_audio_close(); + esd_audio_fd = -1; + return ( -1 ); + } + if ( setup.format.rate != esd_audio_rate || setup.format.voices != 2 + || setup.format.format != SND_PCM_SFMT_S16_LE ) + printf("set format didn't work."); + } + + if( mode == SND_PCM_OPEN_DUPLEX || mode == SND_PCM_OPEN_CAPTURE) { + params.channel = SND_PCM_CHANNEL_CAPTURE; + params.start_mode = SND_PCM_START_DATA; + if ( ( ret = snd_pcm_channel_params( handle, ¶ms ) ) < 0 ) { + fprintf( stderr, "set capture format failed: %s\n", snd_strerror( ret ) ); + esd_audio_close(); + esd_audio_fd = -1; + return ( -1 ); + } + if ( ( ret = snd_pcm_channel_prepare( handle, SND_PCM_CHANNEL_CAPTURE ) ) < 0 ) { + fprintf( stderr, "prapare capture channel failed: %s\n", snd_strerror( ret ) ); + esd_audio_close(); + esd_audio_fd = -1; + return ( -1 ); + memset( &setup, 0, sizeof(setup) ); + setup.mode = SND_PCM_MODE_BLOCK; + setup.channel = SND_PCM_CHANNEL_CAPTURE; + if ( ( ret = snd_pcm_channel_setup( handle, &setup ) ) < 0 ) { + fprintf( stderr, "setup capture channel failed: %s\n", snd_strerror( ret ) ); + esd_audio_close(); + esd_audio_fd = -1; + return ( -1 ); + } + if ( setup.format.rate != esd_audio_rate || setup.format.voices != 2 + || setup.format.format != SND_PCM_SFMT_S16_LE ) + printf("set format didn't work."); + } + } +#else /* ALSA_LIB < 4 */ format.format = ( (esd_audio_format & ESD_MASK_BITS) == ESD_BITS16 ) ? /* 16 bit */ SND_PCM_SFMT_S16_LE : /* 8 bit */ SND_PCM_SFMT_U8; format.rate = esd_audio_rate; @@ -174,9 +264,14 @@ if ( format.rate != esd_audio_rate || format.channels != 2 || format.format != SND_PCM_SFMT_S16_LE ) printf("set format didn't work."); +#endif /* ALSA_LIB */ /* no descriptor for ALSAlib */ +#if ALSA_LIB >= 5 + return ( esd_audio_fd = snd_pcm_file_descriptor( handle, SND_PCM_CHANNEL_PLAYBACK ) ); +#else return ( esd_audio_fd = snd_pcm_file_descriptor( handle ) ); +#endif } #define ARCH_esd_audio_close @@ -205,13 +300,43 @@ { int i=0; i = snd_pcm_write( handle, buffer, buf_size); - writes += i; +#if ALSA_LIB >= 5 + if ( i != buf_size ) { + snd_pcm_channel_status_t status; + memset( &status, 0, sizeof(status) ); + status.channel = SND_PCM_CHANNEL_PLAYBACK; + snd_pcm_channel_status( handle, &status ); +#if ALSA_LIB >= 6 + if ( status.status == SND_PCM_STATUS_XRUN ) +#else + if ( status.status == SND_PCM_STATUS_UNDERRUN ) +#endif + { + snd_pcm_channel_flush( handle, SND_PCM_CHANNEL_PLAYBACK ); + snd_pcm_channel_prepare( handle, SND_PCM_CHANNEL_PLAYBACK ); + } + i = snd_pcm_write( handle, buffer, buf_size ); + } + + if ( i > 0 && i != buf_size ) + i = 0; +#endif + + if ( i >= 0 ) + writes += i; return (i); } #define ARCH_esd_audio_flush void esd_audio_flush() { +#if ALSA_LIB >= 5 + if ( snd_pcm_channel_flush( handle, SND_PCM_CHANNEL_PLAYBACK ) == 0) + snd_pcm_channel_prepare( handle, SND_PCM_CHANNEL_PLAYBACK ); + if ( snd_pcm_channel_flush( handle, SND_PCM_CHANNEL_CAPTURE ) == 0) + snd_pcm_channel_prepare( handle, SND_PCM_CHANNEL_CAPTURE ); +#else fsync( esd_audio_fd ); /*snd_pcm_flush_playback( handle );*/ +#endif }