Index: ao_alsa9.c =================================================================== RCS file: /cvsroot/mplayer/main/libao2/ao_alsa9.c,v retrieving revision 1.30 diff -u -b -B -r1.30 ao_alsa9.c --- ao_alsa9.c 10 Jan 2003 18:28:18 -0000 1.30 +++ ao_alsa9.c 14 Mar 2003 18:41:05 -0000 @@ -77,6 +77,7 @@ #define SET_CHUNKSIZE #undef USE_POLL +static int dropped = 0; /* to set/get/query special features/parameters */ static int control(int cmd, int arg) @@ -766,6 +768,35 @@ } else { if (verbose>0) printf("alsa-reset: reset nonblocked"); + + if (alsa_handler) { + snd_pcm_status_t *status; + int ret; + + if ((ret = snd_pcm_status_malloc(&status)) < 0) + { + printf("alsa-delay: memory allocation error: %s\n", snd_strerror(ret)); + return; + } + + if ((ret = snd_pcm_status(alsa_handler, status)) < 0) + { + printf("alsa-delay: cannot get pcm status: %s\n", snd_strerror(ret)); + return; + } + + switch(snd_pcm_status_get_state(status)) + { + case SND_PCM_STATE_OPEN: + case SND_PCM_STATE_PREPARED: + case SND_PCM_STATE_RUNNING: + dropped = snd_pcm_status_get_delay(status); + break; + default: + dropped = 0; + } + snd_pcm_status_free(status); + } return; } } @@ -829,20 +860,6 @@ return(1); /* ok, data should be accepted again */ } -static int play_normal(void* data, int len); -static int play_mmap(void* data, int len); - -static int play(void* data, int len, int flags) -{ - int result; - if (ao_mmap) - result = play_mmap(data, len); - else - result = play_normal(data, len); - - return result; -} - /* plays 'len' bytes of 'data' returns: number of bytes played @@ -865,6 +882,17 @@ return 0; } + if (dropped > 0) { + if (num_frames < dropped) { + dropped -= num_frames; + return len; + } else { + num_frames -= dropped; + output_samples += dropped*bytes_per_sample; + dropped = 0; + } + } + while (num_frames > 0) { res = snd_pcm_writei(alsa_handler, (void *)output_samples, num_frames); @@ -924,7 +951,22 @@ #ifdef USE_POLL //seems not really be needed struct pollfd *ufds; int count; +#endif + int add = 0; + if (dropped > 0) { + if (len/bytes_per_sample < dropped) { + dropped -= len/bytes_per_sample; + return len; + } else { + len -= dropped*bytes_per_sample; + add = dropped*bytes_per_sample; + data += dropped*bytes_per_sample; + dropped = 0; + } + } + +#ifdef USE_POLL //seems not really be needed count = snd_pcm_poll_descriptors_count (alsa_handler); ufds = malloc(sizeof(struct pollfd) * count); snd_pcm_poll_descriptors(alsa_handler, ufds, count); @@ -1015,6 +1057,16 @@ free(ufds); #endif + return result+add; +} + +static int play(void* data, int len, int flags) +{ + int result; + if (ao_mmap) + result = play_mmap(data, len); + else + result = play_normal(data, len); return result; } @@ -1119,7 +1170,8 @@ case SND_PCM_STATE_OPEN: case SND_PCM_STATE_PREPARED: case SND_PCM_STATE_RUNNING: - ret = (float)snd_pcm_status_get_delay(status)/(float)ao_data.samplerate; + ret = (float)(snd_pcm_status_get_delay(status)-dropped)/(float)ao_data.samplerate; + if (ret < 0) ret = 0; break; default: ret = 0;