diff --git a/configure.in b/configure.in
index 992a886da82b7c2017214591c3c508477d46035c..6d5a844a217e60c710816fa0ab97a4d524fbb45b 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@ AM_DISABLE_STATIC
 dnl Library versioning
 LIB_CURRENT=1
 LIB_REVISION=0
-LIB_AGE=0
+LIB_AGE=1
 AC_SUBST(LIB_CURRENT)
 AC_SUBST(LIB_REVISION)
 AC_SUBST(LIB_AGE)
diff --git a/include/ao/ao.h b/include/ao/ao.h
index 08f1bd9b8b4ea3af345024eb5d5691dba5eb7df7..4311b0f6b17cb7e25f3b93732bb301737c441929 100644
--- a/include/ao/ao.h
+++ b/include/ao/ao.h
@@ -61,6 +61,7 @@ typedef struct ao_functions_s {
 	ao_internal_t *(*open)(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options);
 	void (*play)(ao_internal_t *state, void* output_samples, uint_32 num_bytes);
 	void (*close)(ao_internal_t *state);
+	int (*get_latency)(ao_internal_t *state);
 } ao_functions_t;
 
 typedef struct ao_device_s {
@@ -97,6 +98,9 @@ void ao_close(ao_device_t *device);
 /* misc functions */
 int ao_is_big_endian(void);
 
+/* returns the number of bytes buffered by the driver / output device */
+int ao_get_latency(ao_device_t *device);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/src/ao_null.c b/src/ao_null.c
index 1ffe6b745621778400dd485c873ac875e44f7667..caed4a3fd61899768c87fe8996fcd3a5b7716930 100644
--- a/src/ao_null.c
+++ b/src/ao_null.c
@@ -73,9 +73,15 @@ static ao_info_t *ao_null_get_driver_info(void)
 	return &ao_null_info;
 }
 
+static int ao_null_get_latency(void)
+{
+	return 0;
+}
+
 ao_functions_t ao_null = {
 	ao_null_get_driver_info,
 	ao_null_open,
 	ao_null_play,
-	ao_null_close
+	ao_null_close,
+	ao_null_get_latency
 };
diff --git a/src/ao_wav.c b/src/ao_wav.c
index 47429067fd41d2383833e9cf7481107b238ed059..fe0c022363ddd35c1202dfa4108f5ea41d5aa541 100644
--- a/src/ao_wav.c
+++ b/src/ao_wav.c
@@ -300,6 +300,11 @@ ERR:
 	free(s);
 }
 
+static int ao_wav_get_latency(void)
+{
+	return 0;
+}
+
 static ao_info_t *ao_wav_get_driver_info(void)
 {
 	return &ao_wav_info;
@@ -328,5 +333,6 @@ ao_functions_t ao_wav =
         ao_wav_get_driver_info,
         ao_wav_open,
         ao_wav_play,
-        ao_wav_close
+        ao_wav_close,
+        ao_wav_get_latency
 };
diff --git a/src/audio_out.c b/src/audio_out.c
index 62002bba8866561125438043fd4079999c2bf2f6..b8922960c704cd452e00f42743374064551ca3f3 100644
--- a/src/audio_out.c
+++ b/src/audio_out.c
@@ -84,6 +84,8 @@ driver_tree_t *_get_plugin(char *plugin_file)
 		if (dlerror()) { free(dt->functions); free(dt); return NULL; }
 		dt->functions->close = dlsym(dt->handle, "plugin_close");
 		if (dlerror()) { free(dt->functions); free(dt); return NULL; }
+		dt->functions->get_latency = dlsym(dt->handle, "plugin_get_latency");
+		if (dlerror()) { free(dt->functions); free(dt); return NULL; }
 	} else {
 		return NULL;
 	}
@@ -318,3 +320,9 @@ int ao_is_big_endian(void)
 	if (bytewise[0] == 0xba) return 1;
 	return 0;
 }
+
+int ao_get_latency(ao_device_t *device)
+{
+	return device->funcs->get_latency(device->state);
+}
+
diff --git a/src/plugins/alsa/ao_alsa.c b/src/plugins/alsa/ao_alsa.c
index 30309122216849bf2064a219c246c20b21f43e32..3d9349dc07e7ee0bc63efc358465f51f72b1be97 100644
--- a/src/plugins/alsa/ao_alsa.c
+++ b/src/plugins/alsa/ao_alsa.c
@@ -212,6 +212,14 @@ void plugin_play(ao_internal_t *state, void* output_samples, uint_32 num_bytes)
 	}
 }
 
+int plugin_get_latency(ao_internal_t *state)
+{
+	ao_alsa_internal_t * s = (ao_alsa_internal_t *) state;
+	snd_pcm_channel_status_t status;
+	int err = snd_pcm_channel_status(s->pcm_handle, &status);
+	return (err < 0 ? 0 : status.count);
+}
+
 ao_info_t *plugin_get_driver_info(void)
 {
 	return &ao_alsa_info;
diff --git a/src/plugins/arts/ao_arts.c b/src/plugins/arts/ao_arts.c
index 75a8cfb713bc13b16650bc602819f34243d1e9cd..ff4b88c5521db444f12b57e3ddf962264a46e663 100644
--- a/src/plugins/arts/ao_arts.c
+++ b/src/plugins/arts/ao_arts.c
@@ -32,14 +32,17 @@
 typedef struct ao_arts_internal_s
 {
   arts_stream_t stream;
+	uint_32 bits;
+	uint_32 rate;
+	uint_32 channels;
 } ao_arts_internal_t;
 
 ao_info_t ao_arts_info =
 {
-	"aRts output",
-	"arts",
-	"Rik Hemsley (rikkus) <rik@kde.org>",
-	"Outputs to the aRts soundserver."
+  "aRts output",
+  "arts",
+  "Rik Hemsley (rikkus) <rik@kde.org>",
+  "Outputs to the aRts soundserver."
 };
 
   ao_internal_t *
@@ -74,7 +77,11 @@ plugin_open
 
   state->stream = arts_play_stream(rate, bits, channels, "ao stream");
 
-	return state;
+	state->bits = bits;
+	state->rate = rate;
+	state->channels = channels;
+
+  return state;
 }
 
   void
@@ -102,9 +109,18 @@ plugin_play
   }
 }
 
+  int
+plugin_get_latency(ao_internal_t * state)
+{
+  ao_arts_internal_t * s = (ao_arts_internal_t *)state;
+	int ms = arts_stream_get(s->stream, ARTS_P_TOTAL_LATENCY);
+	int sample_rate = (s->bits / 8) * s->rate * s->channels;
+	return (sample_rate * ms) / 1000;
+}
+
   ao_info_t *
 plugin_get_driver_info(void)
 {
-	return &ao_arts_info;
+  return &ao_arts_info;
 }
 
diff --git a/src/plugins/esd/ao_esd.c b/src/plugins/esd/ao_esd.c
index 16fd3d74e61d21131b47827440a33e0bc9944804..fccfb169ed5e0509bee84e6473d15fd0dc82c33d 100644
--- a/src/plugins/esd/ao_esd.c
+++ b/src/plugins/esd/ao_esd.c
@@ -108,7 +108,7 @@ ao_internal_t *plugin_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_opti
 
 void plugin_close(ao_internal_t *state)
 {
-	ao_esd_internal_t *s = (ao_esd_internal_t *) state;
+	ao_esd_internal_t *s = (ao_esd_internal_t *)state;
 	close(s->sock);
 	free(s->host);
 	free(s);
@@ -119,6 +119,12 @@ void plugin_play(ao_internal_t *state, void* output_samples, uint_32 num_bytes)
 	write(((ao_esd_internal_t *) state)->sock, output_samples, num_bytes);
 }
 
+int plugin_get_latency(ao_internal_t *state)
+{
+	ao_esd_internal_t *s = (ao_esd_internal_t *)state;
+	return (esd_get_latency(s->sock));
+}
+
 ao_info_t *plugin_get_driver_info(void)
 {
 	return &ao_esd_info;
diff --git a/src/plugins/irix/ao_irix.c b/src/plugins/irix/ao_irix.c
index 96dd9723294f0a4f747375715ffed0719558857b..fd7dbd9ab90afb67c8a46d15ff4cfdd5f6474c52 100644
--- a/src/plugins/irix/ao_irix.c
+++ b/src/plugins/irix/ao_irix.c
@@ -163,6 +163,12 @@ void plugin_close(ao_internal_t *state)
 	free(state);
 }
 
+int plugin_get_latency(ao_internal_t *state)
+{
+	/* TODO */
+	return 0;
+}
+
 ao_info_t *plugin_get_driver_info(void)
 {
 	return &ao_irix_info;
diff --git a/src/plugins/oss/ao_oss.c b/src/plugins/oss/ao_oss.c
index 3648553f11ebb875d348c8eb59ec717e4780e519..ba2d48d6037ef18c6a65bf6b8f7ec5fab3feb037 100644
--- a/src/plugins/oss/ao_oss.c
+++ b/src/plugins/oss/ao_oss.c
@@ -166,7 +166,6 @@ ao_internal_t *plugin_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_opti
 	ioctl(state->fd,SNDCTL_DSP_SPEED, &tmp);
 	
 	return state;
-	
 
  ERR:
 	if(state != NULL)
@@ -196,6 +195,12 @@ void plugin_close(ao_internal_t *state)
 	free(s);
 }
 
+int plugin_get_latency(ao_internal_t *state)
+{
+	int odelay = 0;
+	ioctl(((ao_oss_internal_t *)state)->fd, SNDCTL_DSP_GETODELAY, &odelay);
+	return odelay;
+}
 
 ao_info_t *plugin_get_driver_info(void)
 {
diff --git a/src/plugins/solaris/ao_solaris.c b/src/plugins/solaris/ao_solaris.c
index 57c62f763113453b5455ce79a201cdbff0ec7047..d6fcbee18ff7f1413b7f6aeb9b82f5284c781359 100644
--- a/src/plugins/solaris/ao_solaris.c
+++ b/src/plugins/solaris/ao_solaris.c
@@ -122,6 +122,12 @@ void plugin_close(ao_internal_t *state)
 	free(state);
 }
 
+int plugin_get_latency(ao_internal_t *state)
+{
+	/* TODO */
+	return 0;
+}
+
 const ao_info_t *plugin_get_driver_info(void)
 {
 	return &ao_solaris_info;