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;