--- /src/main/libao2/ao_alsa9.c Thu Jun 5 06:02:06 2003 +++ /src/mplayer/libao2/ao_alsa9.c Fri Jun 6 12:35:33 2003 @@ -70,6 +70,7 @@ static int open_mode; static int set_block_mode; +static int alsa_can_pause; #define ALSA_DEVICE_SIZE 48 @@ -285,7 +286,6 @@ default: break; } - bytes_per_sample = ao_data.bps / ao_data.samplerate; if (ao_subdevice) { //start parsing ao_subdevice, ugly and not thread safe! @@ -332,7 +332,24 @@ } } } - } //end parsing ao_subdevice + } else { //end parsing ao_subdevice + /* in any case for multichannel playback we should select + * appropriate device + */ + char devstr[128]; + + switch (channels) { + case 4: + strcpy(devstr, "surround40"); + alsa_device = devstr; + break; + case 6: + strcpy(devstr, "surround51"); + alsa_device = devstr; + break; + default: + } + } /* switch for spdif * sets opening sequence for SPDIF @@ -540,6 +557,18 @@ return (0); } + if ((err = snd_pcm_hw_params_test_format(alsa_handler, alsa_hwparams, + alsa_format)) < 0) + { + printf("alsa-init: format %s are not supported by hardware, trying default\n", + audio_out_format_name(format)); + alsa_format = SND_PCM_FORMAT_S16_LE; + ao_data.format = AFMT_S16_LE; + ao_data.bps = channels * rate_hz * 2; + } + + bytes_per_sample = ao_data.bps / ao_data.samplerate; //it should be here + if ((err = snd_pcm_hw_params_set_format(alsa_handler, alsa_hwparams, alsa_format)) < 0) { @@ -679,6 +708,7 @@ snd_pcm_format_description(alsa_format)); } // end switch alsa_handler (spdif) + alsa_can_pause = snd_pcm_hw_params_can_pause(alsa_hwparams); return(1); } // end init @@ -691,9 +721,9 @@ int err; if (!ao_noblock) { - if ((err = snd_pcm_drain(alsa_handler)) < 0) + if ((err = snd_pcm_drop(alsa_handler)) < 0) { - printf("alsa-uninit: pcm drain error: %s\n", snd_strerror(err)); + printf("alsa-uninit: pcm drop error: %s\n", snd_strerror(err)); return; } } @@ -717,20 +747,36 @@ static void audio_pause() { int err; - - if (!ao_noblock) { - //drain causes error in nonblock-mode! - if ((err = snd_pcm_drain(alsa_handler)) < 0) - { - printf("alsa-pause: pcm drain error: %s\n", snd_strerror(err)); - return; - } - } - else { - if (verbose>0) - printf("alsa-pause: paused nonblock\n"); - - return; + //alsa_can_pause=0; + if (alsa_can_pause) { + if ((err = snd_pcm_pause(alsa_handler, 1)) < 0) + { + printf("alsa-pause: pcm pause error: %s\n", snd_strerror(err)); + return; + } + if (verbose) + printf("alsa-pause: pause supported by hardware\n"); + } else { + if (!ao_noblock) { + //drain causes error in nonblock-mode! + if ((err = snd_pcm_drain(alsa_handler)) < 0) + { + printf("alsa-pause: pcm drain error: %s\n", snd_strerror(err)); + return; + } + if (verbose) + printf("alsa-pause: using drain\n"); + } else { + //may be better call drop always for faster pause + //is sync correct after that? + if ((err = snd_pcm_drop(alsa_handler)) < 0) + { + printf("alsa-pause: pcm drop error: %s\n", snd_strerror(err)); + return; + } + if (verbose) + printf("alsa-pause: using drop for noblock mode\n"); + } } } @@ -738,10 +784,20 @@ { int err; - if ((err = snd_pcm_prepare(alsa_handler)) < 0) - { - printf("alsa-resume: pcm prepare error: %s\n", snd_strerror(err)); - return; + if (alsa_can_pause) { + if ((err = snd_pcm_pause(alsa_handler, 0)) < 0) + { + printf("alsa-resume: pcm resume error: %s\n", snd_strerror(err)); + return; + } + if (verbose) + printf("alsa-resume: resume supported by hardware\n"); + } else { + if ((err = snd_pcm_prepare(alsa_handler)) < 0) + { + printf("alsa-resume: pcm prepare error: %s\n", snd_strerror(err)); + return; + } } } @@ -851,6 +907,8 @@ char *output_samples = (char *)data; snd_pcm_sframes_t res = 0; + len = num_frames * bytes_per_sample; + //fprintf(stderr,"alsa-play: frames=%i, len=%i\n",num_frames,len); if (!alsa_handler) {