changeset 3095:981a9e5118ce

interface to libao2 changed ao_plugin added
author anders
date Sat, 24 Nov 2001 05:21:22 +0000
parents 4150aff2ac17
children 15abd9121737
files libao2/Makefile libao2/ao_alsa1x.c libao2/ao_alsa5.c libao2/ao_alsa9.c libao2/ao_mpegpes.c libao2/ao_null.c libao2/ao_oss.c libao2/ao_pcm.c libao2/ao_sdl.c libao2/ao_sgi.c libao2/ao_sun.c libao2/audio_out.c libao2/audio_out.h libao2/audio_out_internal.h
diffstat 14 files changed, 204 insertions(+), 265 deletions(-) [+]
line wrap: on
line diff
--- a/libao2/Makefile	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/Makefile	Sat Nov 24 05:21:22 2001 +0000
@@ -4,7 +4,7 @@
 LIBNAME = libao2.a
 
 # TODO: moveout ao_sdl.c so it's only used when SDL is detected
-SRCS=afmt.c audio_out.c ao_null.c ao_pcm.c ao_mpegpes.c $(OPTIONAL_SRCS)
+SRCS=afmt.c audio_out.c ao_mpegpes.c ao_null.c ao_pcm.c ao_plugin.c $(OPTIONAL_SRCS)
 OBJS=$(SRCS:.c=.o)
 
 CFLAGS  = $(OPTFLAGS) -I. -I.. $(SDL_INC) $(EXTRA_INC)
@@ -38,3 +38,4 @@
 ifneq ($(wildcard .depend),)
 include .depend
 endif
+
--- a/libao2/ao_alsa1x.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_alsa1x.c	Sat Nov 24 05:21:22 2001 +0000
@@ -32,14 +32,6 @@
 
 LIBAO_EXTERN(alsa9)
 
-/* global variables:
-    ao_samplerate
-    ao_channels
-    ao_format
-    ao_bps
-    ao_outburst
-    ao_buffersize
-*/
 
 static snd_pcm_t *alsa_handler;
 static snd_pcm_format_t alsa_format;
@@ -67,7 +59,7 @@
 
 	    strncpy(alsa_device, (char *)arg, ALSA_DEVICE_SIZE);
 	    uninit();
-	    ret = init(ao_samplerate, ao_channels, ao_format, 0);
+	    ret = init(ao_data.samplerate, ao_data.channels, ao_data.format, 0);
 	    if (ret == 0)
 		return(CONTROL_ERROR);
 	    else
@@ -112,12 +104,12 @@
 	return(0);
     }
 
-    ao_samplerate = rate_hz;
-    ao_bps = channels; /* really this is bytes per frame so bad varname */
-    ao_format = format;
-    ao_channels = channels;
-    ao_outburst = OUTBURST;
-    ao_buffersize = 16384;
+    ao_data.samplerate = rate_hz;
+    ao_data.bps = channels; /* really this is bytes per frame so bad varname */
+    ao_data.format = format;
+    ao_data.channels = channels;
+    ao_data.outburst = OUTBURST;
+    ao_data.buffersize = 16384;
 
     switch (format)
     {
@@ -148,7 +140,7 @@
     {
 	case SND_PCM_FORMAT_S16_LE:
 	case SND_PCM_FORMAT_U16_LE:
-	    ao_bps *= 2;
+	    ao_data.bps *= 2;
 	    break;
 	case -1:
 	    printf("alsa-init: invalid format (%s) requested - output disabled\n",
@@ -164,8 +156,8 @@
 	return(0);
     }
 
-    if (ao_subdevice != NULL)
-	alsa_device = ao_subdevice;
+    if (ao_data.subdevice != NULL)
+	alsa_device = ao_data.subdevice;
 
     if (alsa_device == NULL)
     {
@@ -219,14 +211,14 @@
     }
 
     if ((err = snd_pcm_hw_params_set_channels(alsa_handler, alsa_hwparams,
-	ao_channels)) < 0)
+	ao_data.channels)) < 0)
     {
 	printf("alsa-init: unable to set channels: %s\n",
 	    snd_strerror(err));
 	return(0);
     }
 
-        if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, ao_samplerate, 0)) < 0) 
+        if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, ao_data.samplerate, 0)) < 0) 
 /* was originally only snd_pcm_hw_params_set_rate jp*/ 
         {
     	printf("alsa-init: unable to set samplerate-2: %s\n",
@@ -259,9 +251,9 @@
 	return(0);
     } else
     {
-	ao_buffersize = err;
+	ao_data.buffersize = err;
         if (verbose)
-	    printf("alsa-init: got buffersize %i\n", ao_buffersize);
+	    printf("alsa-init: got buffersize %i\n", ao_data.buffersize);
     }
 #endif
 
@@ -278,7 +270,7 @@
 	    alsa_buffer_time = err;
 
 	if ((err = snd_pcm_hw_params_set_period_time_near(alsa_handler, alsa_hwparams, alsa_buffer_time/4, 0)) < 0)
-	  /* original: alsa_buffer_time/ao_bps */
+	  /* original: alsa_buffer_time/ao_data.bps */
 	{
 	    printf("alsa-init: unable to set period time: %s\n",
 		snd_strerror(err));
@@ -299,7 +291,7 @@
 #ifdef sw_params
     {
     chunk_size = snd_pcm_hw_params_get_period_size(alsa_hwparams, 0);
-    start_threshold = (double) ao_samplerate * start_delay / 1000000;
+    start_threshold = (double) ao_data.samplerate * start_delay / 1000000;
     xfer_align = snd_pcm_sw_params_get_xfer_align(alsa_swparams);
 
     if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0)
@@ -369,7 +361,7 @@
     }
 #endif
     printf("AUDIO: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n",
-	ao_samplerate, ao_channels, ao_bps, ao_buffersize,
+	ao_data.samplerate, ao_data.channels, ao_data.bps, ao_data.buffersize,
 	snd_pcm_format_description(alsa_format));
     return(1);
 }
@@ -488,7 +480,7 @@
 
     got_len = snd_pcm_writei(alsa_handler, data, len / 4);
     
-    //if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_bps))) != (len/ao_bps)) {     
+    //if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps)) {     
     //SHOULD BE FIXED      
 	if (got_len == -EPIPE) /* underrun? */
 	{
@@ -498,7 +490,7 @@
 		printf("alsa-play: playback prepare error: %s\n", snd_strerror(got_len));
 		return(0);
 	    }
-	    if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_bps))) != (len/ao_bps))
+	    if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps))
 	    {
 		printf("alsa-play: write error after reset: %s - giving up\n",
 		    snd_strerror(got_len));
@@ -533,7 +525,7 @@
 	case SND_PCM_STATE_OPEN:
 	case SND_PCM_STATE_PREPARED:
 	case SND_PCM_STATE_RUNNING:
-	    ret = snd_pcm_status_get_avail(status) * ao_bps;
+	    ret = snd_pcm_status_get_avail(status) * ao_data.bps;
 	    break;
 	default:
 	    ret = 0;
@@ -546,11 +538,11 @@
     return(ret);
 }
 
-/* how many unplayed bytes are in the buffer */
-static int get_delay()
+/* delay in seconds between first and last sample in buffer */
+static float get_delay()
 {
     snd_pcm_status_t *status;
-    int ret;
+    float ret;
     
     if ((ret = snd_pcm_status_malloc(&status)) < 0)
     {
@@ -569,7 +561,7 @@
 	case SND_PCM_STATE_OPEN:
 	case SND_PCM_STATE_PREPARED:
 	case SND_PCM_STATE_RUNNING:
-	    ret = snd_pcm_status_get_delay(status) * ao_bps;
+	    ret = (float)snd_pcm_status_get_delay(status)/(float)ao_data.samplerate;
 	    break;
 	default:
 	    ret = 0;
--- a/libao2/ao_alsa5.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_alsa5.c	Sat Nov 24 05:21:22 2001 +0000
@@ -27,15 +27,6 @@
 
 LIBAO_EXTERN(alsa5)
 
-/* global variables:
-    ao_samplerate
-    ao_channels
-    ao_format
-    ao_bps
-    ao_outburst
-    ao_buffersize
-*/
-
 static snd_pcm_t *alsa_handler;
 static snd_pcm_format_t alsa_format;
 static int alsa_rate = SND_PCM_RATE_CONTINUOUS;
@@ -74,12 +65,12 @@
 	return(0);
     }
 
-    ao_format = format;
-    ao_channels = channels - 1;
-    ao_samplerate = rate_hz;
-    ao_bps = ao_samplerate*(ao_channels+1);
-    ao_outburst = OUTBURST;
-    ao_buffersize = 16384;
+    ao_data.format = format;
+    ao_data.channels = channels - 1;
+    ao_data.samplerate = rate_hz;
+    ao_data.bps = ao_data.samplerate*(ao_data.channels+1);
+    ao_data.outburst = OUTBURST;
+    ao_data.buffersize = 16384;
 
     memset(&alsa_format, 0, sizeof(alsa_format));
     switch (format)
@@ -111,7 +102,7 @@
     {
 	case SND_PCM_SFMT_S16_LE:
 	case SND_PCM_SFMT_U16_LE:
-	    ao_bps *= 2;
+	    ao_data.bps *= 2;
 	    break;
 	case -1:
 	    printf("alsa-init: invalid format (%s) requested - output disabled\n",
@@ -161,8 +152,8 @@
 	    break;
     }
 
-    alsa_format.rate = ao_samplerate;
-    alsa_format.voices = ao_channels*2;
+    alsa_format.rate = ao_data.samplerate;
+    alsa_format.voices = ao_data.channels*2;
     alsa_format.interleave = 1;
 
     if ((err = snd_pcm_open(&alsa_handler, 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0)
@@ -189,13 +180,15 @@
 	    printf("alsa-init: pcm channel info error: %s\n", snd_strerror(err));
 	    return(0);
 	}
+
 #ifndef __QNX__
 	if (chninfo.buffer_size)
-	    ao_buffersize = chninfo.buffer_size;
+	    ao_data.buffersize = chninfo.buffer_size;
 #endif
+
 	if (verbose)
 	    printf("alsa-init: setting preferred buffer size from driver: %d bytes\n",
-		ao_buffersize);
+		ao_data.buffersize);
     }
 
     memset(&params, 0, sizeof(params));
@@ -204,7 +197,7 @@
     params.format = alsa_format;
     params.start_mode = SND_PCM_START_DATA;
     params.stop_mode = SND_PCM_STOP_ROLLOVER;
-    params.buf.stream.queue_size = ao_buffersize;
+    params.buf.stream.queue_size = ao_data.buffersize;
     params.buf.stream.fill = SND_PCM_FILL_NONE;
 
     if ((err = snd_pcm_channel_params(alsa_handler, &params)) < 0)
@@ -217,8 +210,8 @@
     setup.channel = SND_PCM_CHANNEL_PLAYBACK;
     setup.mode = SND_PCM_MODE_STREAM;
     setup.format = alsa_format;
-    setup.buf.stream.queue_size = ao_buffersize;
-    setup.msbits_per_sample = ao_bps;
+    setup.buf.stream.queue_size = ao_data.buffersize;
+    setup.msbits_per_sample = ao_data.bps;
     
     if ((err = snd_pcm_channel_setup(alsa_handler, &setup)) < 0)
     {
@@ -233,7 +226,7 @@
     }
 
     printf("AUDIO: %d Hz/%d channels/%d bps/%d bytes buffer/%s\n",
-	ao_samplerate, ao_channels+1, ao_bps, ao_buffersize,
+	ao_data.samplerate, ao_data.channels+1, ao_data.bps, ao_data.buffersize,
 	snd_pcm_get_format_name(alsa_format.format));
     return(1);
 }
@@ -357,15 +350,15 @@
 	return(ch_stat.free);
 }
 
-/* how many unplayed bytes are in the buffer */
-static int get_delay()
+/* delay in seconds between first and last sample in buffer */
+static float get_delay()
 {
     snd_pcm_channel_status_t ch_stat;
     
     ch_stat.channel = SND_PCM_CHANNEL_PLAYBACK;
     
     if (snd_pcm_channel_status(alsa_handler, &ch_stat) < 0)
-	return(ao_buffersize); /* error occured */
+	return((float)ao_data.buffersize/(float)ao_data.bps); /* error occured */
     else
-	return(ch_stat.count);
+	return((float)ch_stat.count/(float)ao_data.bps);
 }
--- a/libao2/ao_alsa9.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_alsa9.c	Sat Nov 24 05:21:22 2001 +0000
@@ -32,14 +32,6 @@
 
 LIBAO_EXTERN(alsa9)
 
-/* global variables:
-    ao_samplerate
-    ao_channels
-    ao_format
-    ao_bps
-    ao_outburst
-    ao_buffersize
-*/
 
 static snd_pcm_t *alsa_handler;
 static snd_pcm_format_t alsa_format;
@@ -67,7 +59,7 @@
 
 	    strncpy(alsa_device, (char *)arg, ALSA_DEVICE_SIZE);
 	    uninit();
-	    ret = init(ao_samplerate, ao_channels, ao_format, 0);
+	    ret = init(ao_data.samplerate, ao_data.channels, ao_data.format, 0);
 	    if (ret == 0)
 		return(CONTROL_ERROR);
 	    else
@@ -112,12 +104,12 @@
 	return(0);
     }
 
-    ao_samplerate = rate_hz;
-    ao_bps = channels; /* really this is bytes per frame so bad varname */
-    ao_format = format;
-    ao_channels = channels;
-    ao_outburst = OUTBURST;
-    ao_buffersize = 16384;
+    ao_data.samplerate = rate_hz;
+    ao_data.bps = channels; /* really this is bytes per frame so bad varname */
+    ao_data.format = format;
+    ao_data.channels = channels;
+    ao_data.outburst = OUTBURST;
+    ao_data.buffersize = 16384;
 
     switch (format)
     {
@@ -148,7 +140,7 @@
     {
 	case SND_PCM_FORMAT_S16_LE:
 	case SND_PCM_FORMAT_U16_LE:
-	    ao_bps *= 2;
+	    ao_data.bps *= 2;
 	    break;
 	case -1:
 	    printf("alsa-init: invalid format (%s) requested - output disabled\n",
@@ -164,8 +156,8 @@
 	return(0);
     }
 
-    if (ao_subdevice != NULL)
-	alsa_device = ao_subdevice;
+    if (ao_data.subdevice != NULL)
+	alsa_device = ao_data.subdevice;
 
     if (alsa_device == NULL)
     {
@@ -219,14 +211,14 @@
     }
 
     if ((err = snd_pcm_hw_params_set_channels(alsa_handler, alsa_hwparams,
-	ao_channels)) < 0)
+	ao_data.channels)) < 0)
     {
 	printf("alsa-init: unable to set channels: %s\n",
 	    snd_strerror(err));
 	return(0);
     }
 
-        if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, ao_samplerate, 0)) < 0) 
+        if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, ao_data.samplerate, 0)) < 0) 
 /* was originally only snd_pcm_hw_params_set_rate jp*/ 
         {
     	printf("alsa-init: unable to set samplerate-2: %s\n",
@@ -259,9 +251,9 @@
 	return(0);
     } else
     {
-	ao_buffersize = err;
+	ao_data.buffersize = err;
         if (verbose)
-	    printf("alsa-init: got buffersize %i\n", ao_buffersize);
+	    printf("alsa-init: got buffersize %i\n", ao_data.buffersize);
     }
 #endif
 
@@ -278,7 +270,7 @@
 	    alsa_buffer_time = err;
 
 	if ((err = snd_pcm_hw_params_set_period_time_near(alsa_handler, alsa_hwparams, alsa_buffer_time/4, 0)) < 0)
-	  /* original: alsa_buffer_time/ao_bps */
+	  /* original: alsa_buffer_time/ao_data.bps */
 	{
 	    printf("alsa-init: unable to set period time: %s\n",
 		snd_strerror(err));
@@ -299,7 +291,7 @@
 #ifdef sw_params
     {
     chunk_size = snd_pcm_hw_params_get_period_size(alsa_hwparams, 0);
-    start_threshold = (double) ao_samplerate * start_delay / 1000000;
+    start_threshold = (double) ao_data.samplerate * start_delay / 1000000;
     xfer_align = snd_pcm_sw_params_get_xfer_align(alsa_swparams);
 
     if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0)
@@ -369,7 +361,7 @@
     }
 #endif
     printf("AUDIO: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n",
-	ao_samplerate, ao_channels, ao_bps, ao_buffersize,
+	ao_data.samplerate, ao_data.channels, ao_data.bps, ao_data.buffersize,
 	snd_pcm_format_description(alsa_format));
     return(1);
 }
@@ -488,7 +480,7 @@
 
     got_len = snd_pcm_writei(alsa_handler, data, len / 4);
     
-    //if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_bps))) != (len/ao_bps)) {     
+    //if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps)) {     
     //SHOULD BE FIXED      
 	if (got_len == -EPIPE) /* underrun? */
 	{
@@ -498,7 +490,7 @@
 		printf("alsa-play: playback prepare error: %s\n", snd_strerror(got_len));
 		return(0);
 	    }
-	    if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_bps))) != (len/ao_bps))
+	    if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps))
 	    {
 		printf("alsa-play: write error after reset: %s - giving up\n",
 		    snd_strerror(got_len));
@@ -533,7 +525,7 @@
 	case SND_PCM_STATE_OPEN:
 	case SND_PCM_STATE_PREPARED:
 	case SND_PCM_STATE_RUNNING:
-	    ret = snd_pcm_status_get_avail(status) * ao_bps;
+	    ret = snd_pcm_status_get_avail(status) * ao_data.bps;
 	    break;
 	default:
 	    ret = 0;
@@ -546,11 +538,11 @@
     return(ret);
 }
 
-/* how many unplayed bytes are in the buffer */
-static int get_delay()
+/* delay in seconds between first and last sample in buffer */
+static float get_delay()
 {
     snd_pcm_status_t *status;
-    int ret;
+    float ret;
     
     if ((ret = snd_pcm_status_malloc(&status)) < 0)
     {
@@ -569,7 +561,7 @@
 	case SND_PCM_STATE_OPEN:
 	case SND_PCM_STATE_PREPARED:
 	case SND_PCM_STATE_RUNNING:
-	    ret = snd_pcm_status_get_delay(status) * ao_bps;
+	    ret = (float)snd_pcm_status_get_delay(status)/(float)ao_data.samplerate;
 	    break;
 	default:
 	    ret = 0;
--- a/libao2/ao_mpegpes.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_mpegpes.c	Sat Nov 24 05:21:22 2001 +0000
@@ -16,13 +16,6 @@
 
 LIBAO_EXTERN(mpegpes)
 
-// there are some globals:
-// ao_samplerate
-// ao_channels
-// ao_format
-// ao_bps
-// ao_outburst
-// ao_buffersize
 
 // to set/get/query special features/parameters
 static int control(int cmd,int arg){
@@ -33,8 +26,8 @@
 // return: 1=success 0=fail
 static int init(int rate,int channels,int format,int flags){
 
-    ao_outburst=2000;
-    ao_format=format;
+    ao_data.outburst=2000;
+    ao_data.format=format;
 
     return 1;
 }
@@ -67,10 +60,10 @@
 
 // return: how many bytes can be played without blocking
 static int get_space(){
-    float x=(float)(vo_pts-ao_pts)/90000.0-0.5;
+    float x=(float)(vo_pts-ao_data.pts)/90000.0-0.5;
     int y;
     if(x<=0) return 0;
-    y=48000*4*x;y/=ao_outburst;y*=ao_outburst;
+    y=48000*4*x;y/=ao_data.outburst;y*=ao_data.outburst;
 //    printf("diff: %5.3f -> %d  \n",x,y);
     return y;
 }
@@ -79,20 +72,20 @@
 // it should round it down to outburst*n
 // return: number of bytes played
 static int play(void* data,int len,int flags){
-    if(ao_format==AFMT_MPEG)
-	send_pes_packet(data,len,0x1C0,ao_pts);
+    if(ao_data.format==AFMT_MPEG)
+	send_pes_packet(data,len,0x1C0,ao_data.pts);
     else {
 	int i;
 	unsigned short *s=data;
 	for(i=0;i<len/2;i++) s[i]=(s[i]>>8)|(s[i]<<8); // le<->be
-	send_lpcm_packet(data,len,0xA0,ao_pts);
+	send_lpcm_packet(data,len,0xA0,ao_data.pts);
     }
     return len;
 }
 
-// return: how many unplayed bytes are in the buffer
-static int get_delay(){
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(){
 
-    return 0;
+    return 0.0;
 }
 
--- a/libao2/ao_null.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_null.c	Sat Nov 24 05:21:22 2001 +0000
@@ -14,13 +14,6 @@
 
 LIBAO_EXTERN(null)
 
-// there are some globals:
-// ao_samplerate
-// ao_channels
-// ao_format
-// ao_bps
-// ao_outburst
-// ao_buffersize
 
 // to set/get/query special features/parameters
 static int control(int cmd,int arg){
@@ -31,7 +24,7 @@
 // return: 1=success 0=fail
 static int init(int rate,int channels,int format,int flags){
 
-    ao_outburst=4096;
+    ao_data.outburst=4096;
 
     return 0;
 }
@@ -61,7 +54,7 @@
 // return: how many bytes can be played without blocking
 static int get_space(){
 
-    return ao_outburst;
+    return ao_data.outburst;
 }
 
 // plays 'len' bytes of 'data'
@@ -72,10 +65,10 @@
     return len;
 }
 
-// return: how many unplayed bytes are in the buffer
-static int get_delay(){
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(){
 
-    return 0;
+    return 0.0;
 }
 
 
--- a/libao2/ao_oss.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_oss.c	Sat Nov 24 05:21:22 2001 +0000
@@ -28,14 +28,6 @@
 
 LIBAO_EXTERN(oss)
 
-// there are some globals:
-// ao_samplerate
-// ao_channels
-// ao_format
-// ao_bps
-// ao_outburst
-// ao_buffersize
-
 static char *dsp="/dev/dsp";
 static audio_buf_info zz;
 static int audio_fd=-1;
@@ -57,7 +49,7 @@
 	    ao_control_vol_t *vol = (ao_control_vol_t *)arg;
 	    int fd, v, mcmd, devs;
 
-	    if(ao_format == AFMT_AC3)
+	    if(ao_data.format == AFMT_AC3)
 		return CONTROL_TRUE;
     
 	    if ((fd = open("/dev/mixer", O_RDONLY)) > 0)
@@ -118,58 +110,62 @@
     return 0;
   }
 
-  ao_format=format;
-  ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_format);
-  if(format == AFMT_AC3 && ao_format != AFMT_AC3) {
+  ao_data.bps=(channels+1)*rate;
+  if(format != AFMT_U8 && format != AFMT_S8)
+    ao_data.bps*=2;
+
+  ao_data.format=format;
+  ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_data.format);
+  if(format == AFMT_AC3 && ao_data.format != AFMT_AC3) {
       printf("Can't set audio device %s to AC3 output\n", dsp);
       return 0;
   }
   printf("audio_setup: sample format: %s (requested: %s)\n",
-    audio_out_format_name(ao_format), audio_out_format_name(format));
+    audio_out_format_name(ao_data.format), audio_out_format_name(format));
   
   if(format != AFMT_AC3) {
-  ao_channels=channels-1;
-  ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_channels);
+  ao_data.channels=channels-1;
+  ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_data.channels);
   
   // set rate
-  ao_samplerate=rate;
-  ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate);
-  printf("audio_setup: using %d Hz samplerate (requested: %d)\n",ao_samplerate,rate);
+  ao_data.samplerate=rate;
+  ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate);
+  printf("audio_setup: using %d Hz samplerate (requested: %d)\n",ao_data.samplerate,rate);
   }
 
   if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){
       int r=0;
       printf("audio_setup: driver doesn't support SNDCTL_DSP_GETOSPACE :-(\n");
       if(ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &r)==-1){
-          printf("audio_setup: %d bytes/frag (config.h)\n",ao_outburst);
+          printf("audio_setup: %d bytes/frag (config.h)\n",ao_data.outburst);
       } else {
-          ao_outburst=r;
-          printf("audio_setup: %d bytes/frag (GETBLKSIZE)\n",ao_outburst);
+          ao_data.outburst=r;
+          printf("audio_setup: %d bytes/frag (GETBLKSIZE)\n",ao_data.outburst);
       }
   } else {
       printf("audio_setup: frags: %3d/%d  (%d bytes/frag)  free: %6d\n",
           zz.fragments, zz.fragstotal, zz.fragsize, zz.bytes);
-      if(ao_buffersize==-1) ao_buffersize=zz.bytes;
-      ao_outburst=zz.fragsize;
+      if(ao_data.buffersize==-1) ao_data.buffersize=zz.bytes;
+      ao_data.outburst=zz.fragsize;
   }
 
-  if(ao_buffersize==-1){
+  if(ao_data.buffersize==-1){
     // Measuring buffer size:
     void* data;
-    ao_buffersize=0;
+    ao_data.buffersize=0;
 #ifdef HAVE_AUDIO_SELECT
-    data=malloc(ao_outburst); memset(data,0,ao_outburst);
-    while(ao_buffersize<0x40000){
+    data=malloc(ao_data.outburst); memset(data,0,ao_data.outburst);
+    while(ao_data.buffersize<0x40000){
       fd_set rfds;
       struct timeval tv;
       FD_ZERO(&rfds); FD_SET(audio_fd,&rfds);
       tv.tv_sec=0; tv.tv_usec = 0;
       if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) break;
-      write(audio_fd,data,ao_outburst);
-      ao_buffersize+=ao_outburst;
+      write(audio_fd,data,ao_data.outburst);
+      ao_data.buffersize+=ao_data.outburst;
     }
     free(data);
-    if(ao_buffersize==0){
+    if(ao_data.buffersize==0){
         printf("\n   ***  Your audio driver DOES NOT support select()  ***\n");
           printf("Recompile mplayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n");
         return 0;
@@ -197,10 +193,10 @@
 	return;
     }
 
-  ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_format);
-  if(ao_format != AFMT_AC3) {
-  ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_channels);
-  ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate);
+  ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_data.format);
+  if(ao_data.format != AFMT_AC3) {
+  ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_data.channels);
+  ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate);
   }
 }
 
@@ -219,7 +215,7 @@
 
 // return: how many bytes can be played without blocking
 static int get_space(){
-  int playsize=ao_outburst;
+  int playsize=ao_data.outburst;
 
 #ifdef SNDCTL_DSP_GETOSPACE
   if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)!=-1){
@@ -240,35 +236,38 @@
     }
 #endif
 
-  return ao_outburst;
+  return ao_data.outburst;
 }
 
 // plays 'len' bytes of 'data'
 // it should round it down to outburst*n
 // return: number of bytes played
 static int play(void* data,int len,int flags){
-    len/=ao_outburst;
-    len=write(audio_fd,data,len*ao_outburst);
+    len/=ao_data.outburst;
+    len=write(audio_fd,data,len*ao_data.outburst);
     return len;
 }
 
 static int audio_delay_method=2;
 
-// return: how many unplayed bytes are in the buffer
-static int get_delay(){
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(){
+  /* Calculate how many bytes/second is sent out */
   if(audio_delay_method==2){
-      // 
       int r=0;
       if(ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &r)!=-1)
-         return r;
+         return ((float)r)/(float)ao_data.bps;
       audio_delay_method=1; // fallback if not supported
   }
   if(audio_delay_method==1){
       // SNDCTL_DSP_GETOSPACE
       if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)!=-1)
-         return ao_buffersize-zz.bytes;
+         return ((float)(ao_data.buffersize-zz.bytes))/(float)ao_data.bps;
       audio_delay_method=0; // fallback if not supported
   }
-  return ao_buffersize;
+  return ((float)ao_data.buffersize)/(float)ao_data.bps;
 }
 
+
+
+
--- a/libao2/ao_pcm.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_pcm.c	Sat Nov 24 05:21:22 2001 +0000
@@ -14,14 +14,6 @@
 
 LIBAO_EXTERN(pcm)
 
-// there are some globals:
-// ao_samplerate
-// ao_channels
-// ao_format
-// ao_bps
-// ao_outburst
-// ao_buffersize
-
 char *ao_outputfilename = NULL;
 int ao_pcm_waveheader = 1;
 
@@ -90,7 +82,7 @@
 	printf("PCM: Info - to write WAVE files use -waveheader (default), for RAW PCM -nowaveheader.\n");
 	fp = fopen(ao_outputfilename, "wb");
 
-	ao_outburst = 4096;
+	ao_data.outburst = 4096;
 
 
 	if(fp) {
@@ -134,7 +126,7 @@
 // return: how many bytes can be played without blocking
 static int get_space(){
 
-    return ao_outburst;
+    return ao_data.outburst;
 }
 
 // plays 'len' bytes of 'data'
@@ -151,10 +143,10 @@
 	return len;
 }
 
-// return: how many unplayed bytes are in the buffer
-static int get_delay(){
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(){
 
-    return 0;
+    return 0.0;
 }
 
 
--- a/libao2/ao_sdl.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_sdl.c	Sat Nov 24 05:21:22 2001 +0000
@@ -29,13 +29,6 @@
 
 LIBAO_EXTERN(sdl)
 
-// there are some globals:
-// ao_samplerate
-// ao_channels
-// ao_format
-// ao_bps
-// ao_outburst
-// ao_buffersize
 
 extern int verbose;
 
@@ -150,6 +143,10 @@
 		setenv("SDL_AUDIODRIVER", ao_subdevice, 1);
 		printf("SDL: using %s audio driver\n", ao_subdevice);
 	}
+
+	ao_data.bps=(channels+1)*rate;
+	if(format != AFMT_U8 && format != AFMT_S8)
+	  ao_data.bps*=2;
 	
 	/* The desired audio format (see SDL_AudioSpec) */
 	switch(format) {
@@ -205,7 +202,7 @@
 	} 
 	
 	if(verbose) printf("SDL: buf size = %d\n",aspec.size);
-	if(ao_buffersize==-1) ao_buffersize=aspec.size;
+	if(ao_data.buffersize==-1) ao_data.buffersize=aspec.size;
 	
 	/* unsilence audio, if callback is ready */
 	SDL_PauseAudio(0);
@@ -278,9 +275,9 @@
 #endif
 }
 
-// return: how many unplayed bytes are in the buffer
-static int get_delay(){
-    return buffered_bytes + ao_buffersize;
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(){
+    return (float)(buffered_bytes + ao_data.buffersize)/(float)ao_data.bps;
 }
 
 
--- a/libao2/ao_sgi.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_sgi.c	Sat Nov 24 05:21:22 2001 +0000
@@ -22,13 +22,6 @@
 
 LIBAO_EXTERN(sgi)
 
-// there are some globals:
-// ao_samplerate
-// ao_channels
-// ao_format
-// ao_bps
-// ao_outburst
-// ao_buffersize
 
 static ALconfig	ao_config;
 static ALport	ao_port;
@@ -86,9 +79,9 @@
 
   }
   
-  ao_buffersize=131072;
-  ao_outburst = ao_buffersize/16;
-  ao_channels = channels;
+  ao_data.buffersize=131072;
+  ao_data.outburst = ao_data.buffersize/16;
+  ao_data.channels = channels;
   
   ao_config = alNewConfig();
   
@@ -164,7 +157,7 @@
   // printf("ao_sgi, get_space: (ao_outburst %d)\n", ao_outburst);
   // printf("ao_sgi, get_space: alGetFillable [%d] \n", alGetFillable(ao_port));
   
-  return alGetFillable(ao_port)*(2*ao_channels);
+  return alGetFillable(ao_port)*(2*ao_data.channels);
     
 }
 
@@ -177,14 +170,14 @@
   // printf("ao_sgi, play: len %d flags %d (%d %d)\n", len, flags, ao_port, ao_config);
   // printf("channels %d\n", ao_channels);
 
-  alWriteFrames(ao_port, data, len/(2*ao_channels));
+  alWriteFrames(ao_port, data, len/(2*ao_data.channels));
   
   return len;
   
 }
 
-// return: how many unplayed bytes are in the buffer
-static int get_delay(){
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(){
   
   // printf("ao_sgi, get_delay: (ao_buffersize %d)\n", ao_buffersize);
   
--- a/libao2/ao_sun.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/ao_sun.c	Sat Nov 24 05:21:22 2001 +0000
@@ -42,18 +42,11 @@
 #endif
 
 
-// there are some globals:
-// ao_samplerate
-// ao_channels
-// ao_format
-// ao_bps
-// ao_outburst
-// ao_buffersize
-
 static char *audio_dev = "/dev/audio";
 static int queued_bursts = 0;
 static int queued_samples = 0;
 static int bytes_per_sample = 0;
+static int byte_per_sec = 0;
 static int convert_u8_s8;
 static int audio_fd = -1;
 static enum {
@@ -230,7 +223,6 @@
 static int init(int rate,int channels,int format,int flags){
 
     audio_info_t info;
-    int byte_per_sec;
     int ok;
 
     if (ao_subdevice) audio_dev = ao_subdevice;
@@ -252,13 +244,13 @@
     ioctl(audio_fd, AUDIO_DRAIN, 0);
 
     AUDIO_INITINFO(&info);
-    info.play.encoding = oss2sunfmt(ao_format = format);
+    info.play.encoding = oss2sunfmt(ao_data.format = format);
     info.play.precision =
 	(format==AFMT_S16_LE || format==AFMT_S16_BE
 	 ? AUDIO_PRECISION_16
 	 : AUDIO_PRECISION_8);
-    info.play.channels = ao_channels = channels;
-    info.play.sample_rate = ao_samplerate = rate;
+    info.play.channels = ao_data.channels = channels;
+    info.play.sample_rate = ao_data.samplerate = rate;
     convert_u8_s8 = 0;
     ok = ioctl(audio_fd, AUDIO_SETINFO, &info) >= 0;
     if (!ok && info.play.encoding == AUDIO_ENCODING_LINEAR8) {
@@ -278,37 +270,37 @@
 
     bytes_per_sample = channels * info.play.precision / 8;
     byte_per_sec = bytes_per_sample * rate;
-    ao_outburst = byte_per_sec > 100000 ? 16384 : 8192;
+    ao_data.outburst = byte_per_sec > 100000 ? 16384 : 8192;
 
 #ifdef	__not_used__
     /*
-     * hmm, ao_buffersize is currently not used in this driver, do there's
+     * hmm, ao_data.buffersize is currently not used in this driver, do there's
      * no need to measure it
      */
-    if(ao_buffersize==-1){
+    if(ao_data.buffersize==-1){
 	// Measuring buffer size:
 	void* data;
-	ao_buffersize=0;
+	ao_data.buffersize=0;
 #ifdef HAVE_AUDIO_SELECT
-	data = malloc(ao_outburst);
-	memset(data, format==AFMT_U8 ? 0x80 : 0, ao_outburst);
-	while(ao_buffersize<0x40000){
+	data = malloc(ao_data.outburst);
+	memset(data, format==AFMT_U8 ? 0x80 : 0, ao_data.outburst);
+	while(ao_data.buffersize<0x40000){
 	    fd_set rfds;
 	    struct timeval tv;
 	    FD_ZERO(&rfds); FD_SET(audio_fd,&rfds);
 	    tv.tv_sec=0; tv.tv_usec = 0;
 	    if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) break;
-	    write(audio_fd,data,ao_outburst);
-	    ao_buffersize+=ao_outburst;
+	    write(audio_fd,data,ao_data.outburst);
+	    ao_data.buffersize+=ao_data.outburst;
 	}
 	free(data);
-	if(ao_buffersize==0){
+	if(ao_data.buffersize==0){
 	    printf("\n   ***  Your audio driver DOES NOT support select()  ***\n");
 	    printf("Recompile mplayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n");
 	    return 0;
 	}
 #ifdef	__svr4__
-	// remove the 0 bytes from the above ao_buffersize measurement from the
+	// remove the 0 bytes from the above ao_data.buffersize measurement from the
 	// audio driver's STREAMS queue
 	ioctl(audio_fd, I_FLUSH, FLUSHW);
 #endif
@@ -352,13 +344,13 @@
     ioctl(audio_fd, AUDIO_DRAIN, 0);
 
     AUDIO_INITINFO(&info);
-    info.play.encoding = oss2sunfmt(ao_format);
+    info.play.encoding = oss2sunfmt(ao_data.format);
     info.play.precision =
-	(ao_format==AFMT_S16_LE || ao_format==AFMT_S16_BE 
+	(ao_data.format==AFMT_S16_LE || ao_data.format==AFMT_S16_BE 
 	 ? AUDIO_PRECISION_16
 	 : AUDIO_PRECISION_8);
-    info.play.channels = ao_channels;
-    info.play.sample_rate = ao_samplerate;
+    info.play.channels = ao_data.channels;
+    info.play.sample_rate = ao_data.samplerate;
     info.play.samples = 0;
     info.play.eof = 0;
     info.play.error = 0;
@@ -388,7 +380,7 @@
 
 // return: how many bytes can be played without blocking
 static int get_space(){
-    int playsize = ao_outburst;
+    int playsize = ao_data.outburst;
     audio_info_t info;
 
     // check buffer
@@ -408,7 +400,7 @@
     if (queued_bursts - info.play.eof > 2)
 	return 0;
 
-    return ao_outburst;
+    return ao_data.outburst;
 }
 
 // plays 'len' bytes of 'data'
@@ -421,13 +413,13 @@
     int native_endian = AFMT_S16_LE;
 #endif
 
-    if (len < ao_outburst) return 0;
-    len /= ao_outburst;
-    len *= ao_outburst;
+    if (len < ao_data.outburst) return 0;
+    len /= ao_data.outburst;
+    len *= ao_data.outburst;
 
     /* 16-bit format using the 'wrong' byteorder?  swap words */
-    if ((ao_format == AFMT_S16_LE || ao_format == AFMT_S16_BE)
-	&& ao_format != native_endian) {
+    if ((ao_data.format == AFMT_S16_LE || ao_data.format == AFMT_S16_BE)
+	&& ao_data.format != native_endian) {
 	static void *swab_buf;
 	static int swab_len;
 	if (len > swab_len) {
@@ -440,7 +432,7 @@
 	}
 	swab(data, swab_buf, len);
 	data = swab_buf;
-    } else if (ao_format == AFMT_U8 && convert_u8_s8) {
+    } else if (ao_data.format == AFMT_U8 && convert_u8_s8) {
 	int i;
 	unsigned char *p = data;
 
@@ -460,13 +452,13 @@
 }
 
 
-// return: how many unplayed bytes are in the buffer
-static int get_delay(){
+// return: delay in seconds between first and last sample in buffer
+static float get_delay(){
     audio_info_t info;
     ioctl(audio_fd, AUDIO_GETINFO, &info);
     if (info.play.samples && enable_sample_timing == RTSC_ENABLED)
-	return (queued_samples - info.play.samples) * bytes_per_sample;
+	return (float)(queued_samples - info.play.samples) / (float)byte_per_sec;
     else
-	return (queued_bursts - info.play.eof) * ao_outburst;
+	return (flaot)((queued_bursts - info.play.eof) * ao_data.outburst) / (float)byte_per_sec;
 }
 
--- a/libao2/audio_out.c	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/audio_out.c	Sat Nov 24 05:21:22 2001 +0000
@@ -6,19 +6,12 @@
 #include "afmt.h"
 
 // there are some globals:
-int ao_samplerate=0;
-int ao_channels=0;
-int ao_format=0;
-int ao_bps=0;
-int ao_outburst=OUTBURST; // config.h default
-int ao_buffersize=-1;
-int ao_pts=0;
+ao_data_t ao_data={0,0,0,0,OUTBURST,-1,0};
 char *ao_subdevice = NULL;
 
 #ifdef USE_OSS_AUDIO
 extern ao_functions_t audio_out_oss;
 #endif
-//extern ao_functions_t audio_out_ossold;
 extern ao_functions_t audio_out_null;
 #ifdef HAVE_ALSA5
  extern ao_functions_t audio_out_alsa5;
@@ -42,10 +35,9 @@
 extern ao_functions_t audio_out_dxr3;
 #endif
 extern ao_functions_t audio_out_pcm;
-#ifndef USE_LIBVO2
 extern ao_functions_t audio_out_mpegpes;
-#endif
 extern ao_functions_t audio_out_pss;
+extern ao_functions_t audio_out_plugin;
 
 ao_functions_t* audio_out_drivers[] =
 {
@@ -75,9 +67,11 @@
 	&audio_out_dxr3,
 #endif
 	&audio_out_pcm,
-#ifndef USE_LIBVO2
 	&audio_out_mpegpes,
-#endif
+	&audio_out_plugin,
 //	&audio_out_pss,
 	NULL
 };
+
+
+
--- a/libao2/audio_out.h	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/audio_out.h	Sat Nov 24 05:21:22 2001 +0000
@@ -10,6 +10,7 @@
         const char *comment;
 } ao_info_t;
 
+/* interface towards mplayer and */
 typedef struct ao_functions_s
 {
 	ao_info_t *info;
@@ -19,25 +20,32 @@
         void (*reset)();
         int (*get_space)();
         int (*play)(void* data,int len,int flags);
-        int (*get_delay)();
+        float (*get_delay)();
         void (*pause)();
         void (*resume)();
 } ao_functions_t;
 
+/* global data used by mplayer and plugins */
+typedef struct ao_data_s
+{
+  int samplerate;
+  int channels;
+  int format;
+  int bps;
+  int outburst; 	  
+  int buffersize;         
+  int pts;
+} ao_data_t;
+
+extern char *ao_subdevice;
+extern ao_data_t ao_data;
+
 // prototypes
 extern char *audio_out_format_name(int format);
 
 // NULL terminated array of all drivers
 extern ao_functions_t* audio_out_drivers[];
 
-extern int ao_samplerate;
-extern int ao_channels;
-extern int ao_format;
-extern int ao_bps;
-extern int ao_outburst;
-extern int ao_buffersize;
-extern int ao_pts;
-extern char *ao_subdevice;
 
 #define CONTROL_OK 1
 #define CONTROL_TRUE 1
--- a/libao2/audio_out_internal.h	Sat Nov 24 02:05:06 2001 +0000
+++ b/libao2/audio_out_internal.h	Sat Nov 24 05:21:22 2001 +0000
@@ -7,7 +7,7 @@
 static void reset();
 static int get_space();
 static int play(void* data,int len,int flags);
-static int get_delay();
+static float get_delay();
 static void audio_pause();
 static void audio_resume();