From ac4fc4026c3b1b0b9487216399bef04d419b04b8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 17 Aug 2012 13:38:52 -0700 Subject: Add a device method to retrieve the active latency This is effectively the time until the next update will be heard by the user, or the closest approximation thereof, in nanoseconds. --- Alc/backends/alsa.c | 21 ++++++++++++++++++++- Alc/backends/coreaudio.c | 10 +++++++++- Alc/backends/dsound.c | 11 ++++++++++- Alc/backends/loopback.c | 11 ++++++++++- Alc/backends/mmdevapi.c | 10 +++++++++- Alc/backends/null.c | 11 ++++++++++- Alc/backends/opensl.c | 10 +++++++++- Alc/backends/oss.c | 10 +++++++++- Alc/backends/portaudio.c | 10 +++++++++- Alc/backends/pulseaudio.c | 23 ++++++++++++++++++++++- Alc/backends/sndio.c | 10 +++++++++- Alc/backends/solaris.c | 10 +++++++++- Alc/backends/wave.c | 11 ++++++++++- Alc/backends/winmm.c | 10 +++++++++- 14 files changed, 154 insertions(+), 14 deletions(-) (limited to 'Alc/backends') diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c index 49fec523..880f7ac9 100644 --- a/Alc/backends/alsa.c +++ b/Alc/backends/alsa.c @@ -79,6 +79,7 @@ MAKE_FUNC(snd_pcm_start); MAKE_FUNC(snd_pcm_resume); MAKE_FUNC(snd_pcm_reset); MAKE_FUNC(snd_pcm_wait); +MAKE_FUNC(snd_pcm_delay); MAKE_FUNC(snd_pcm_state); MAKE_FUNC(snd_pcm_avail_update); MAKE_FUNC(snd_pcm_areas_silence); @@ -151,6 +152,7 @@ MAKE_FUNC(snd_card_next); #define snd_pcm_resume psnd_pcm_resume #define snd_pcm_reset psnd_pcm_reset #define snd_pcm_wait psnd_pcm_wait +#define snd_pcm_delay psnd_pcm_delay #define snd_pcm_state psnd_pcm_state #define snd_pcm_avail_update psnd_pcm_avail_update #define snd_pcm_areas_silence psnd_pcm_areas_silence @@ -241,6 +243,7 @@ static ALCboolean alsa_load(void) LOAD_FUNC(snd_pcm_resume); LOAD_FUNC(snd_pcm_reset); LOAD_FUNC(snd_pcm_wait); + LOAD_FUNC(snd_pcm_delay); LOAD_FUNC(snd_pcm_state); LOAD_FUNC(snd_pcm_avail_update); LOAD_FUNC(snd_pcm_areas_silence); @@ -1224,6 +1227,21 @@ static void alsa_stop_capture(ALCdevice *Device) } +static ALint64 alsa_get_latency(ALCdevice *device) +{ + alsa_data *data = (alsa_data*)device->ExtraData; + snd_pcm_sframes_t delay = 0; + int err; + + if((err=snd_pcm_delay(data->pcmHandle, &delay)) < 0) + { + ERR("Failed to get latency!\n"); + return 0; + } + return maxi64((ALint64)delay*1000000000/device->Frequency, 0); +} + + static const BackendFuncs alsa_funcs = { alsa_open_playback, alsa_close_playback, @@ -1235,7 +1253,8 @@ static const BackendFuncs alsa_funcs = { alsa_start_capture, alsa_stop_capture, alsa_capture_samples, - alsa_available_samples + alsa_available_samples, + alsa_get_latency }; ALCboolean alc_alsa_init(BackendFuncs *func_list) diff --git a/Alc/backends/coreaudio.c b/Alc/backends/coreaudio.c index a4f72468..df28d706 100644 --- a/Alc/backends/coreaudio.c +++ b/Alc/backends/coreaudio.c @@ -663,6 +663,13 @@ static ALCuint ca_available_samples(ALCdevice *device) } +static ALint64 ca_get_latency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs ca_funcs = { ca_open_playback, ca_close_playback, @@ -674,7 +681,8 @@ static const BackendFuncs ca_funcs = { ca_start_capture, ca_stop_capture, ca_capture_samples, - ca_available_samples + ca_available_samples, + ca_get_latency }; ALCboolean alc_ca_init(BackendFuncs *func_list) diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index a80d2a99..89910c7f 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -934,6 +934,14 @@ done: return RingBufferSize(data->Ring); } + +static ALint64 DSoundGetLatency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs DSoundFuncs = { DSoundOpenPlayback, DSoundClosePlayback, @@ -945,7 +953,8 @@ static const BackendFuncs DSoundFuncs = { DSoundStartCapture, DSoundStopCapture, DSoundCaptureSamples, - DSoundAvailableSamples + DSoundAvailableSamples, + DSoundGetLatency }; diff --git a/Alc/backends/loopback.c b/Alc/backends/loopback.c index eafed3e3..ae7e32b4 100644 --- a/Alc/backends/loopback.c +++ b/Alc/backends/loopback.c @@ -54,6 +54,14 @@ static void loopback_stop_playback(ALCdevice *device) (void)device; } + +static ALint64 loopback_get_latency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs loopback_funcs = { loopback_open_playback, loopback_close_playback, @@ -65,7 +73,8 @@ static const BackendFuncs loopback_funcs = { NULL, NULL, NULL, - NULL + NULL, + loopback_get_latency }; ALCboolean alc_loopback_init(BackendFuncs *func_list) diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c index 0edd8e60..bffc463a 100644 --- a/Alc/backends/mmdevapi.c +++ b/Alc/backends/mmdevapi.c @@ -937,6 +937,13 @@ static void MMDevApiStopPlayback(ALCdevice *device) } +static ALint64 MMDevApiGetLatency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs MMDevApiFuncs = { MMDevApiOpenPlayback, MMDevApiClosePlayback, @@ -948,7 +955,8 @@ static const BackendFuncs MMDevApiFuncs = { NULL, NULL, NULL, - NULL + NULL, + MMDevApiGetLatency }; diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 1b9bedef..f39d3071 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -129,6 +129,14 @@ static void null_stop_playback(ALCdevice *device) } +static ALint64 null_get_latency(ALCdevice *device) +{ + /* FIXME: Time until next update + "safe" offset */ + (void)device; + return 0; +} + + static const BackendFuncs null_funcs = { null_open_playback, null_close_playback, @@ -140,7 +148,8 @@ static const BackendFuncs null_funcs = { NULL, NULL, NULL, - NULL + NULL, + null_get_latency }; ALCboolean alc_null_init(BackendFuncs *func_list) diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c index bf243e38..f2df0218 100644 --- a/Alc/backends/opensl.c +++ b/Alc/backends/opensl.c @@ -401,6 +401,13 @@ static void opensl_stop_playback(ALCdevice *Device) } +static ALint64 opensl_get_latency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs opensl_funcs = { opensl_open_playback, opensl_close_playback, @@ -412,7 +419,8 @@ static const BackendFuncs opensl_funcs = { NULL, NULL, NULL, - NULL + NULL, + opensl_get_latency }; diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c index 365bb802..6786f8c6 100644 --- a/Alc/backends/oss.c +++ b/Alc/backends/oss.c @@ -476,6 +476,13 @@ static ALCuint oss_available_samples(ALCdevice *Device) } +static ALint64 oss_get_latency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs oss_funcs = { oss_open_playback, oss_close_playback, @@ -487,7 +494,8 @@ static const BackendFuncs oss_funcs = { oss_start_capture, oss_stop_capture, oss_capture_samples, - oss_available_samples + oss_available_samples, + oss_get_latency }; ALCboolean alc_oss_init(BackendFuncs *func_list) diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c index b9998150..1558e89f 100644 --- a/Alc/backends/portaudio.c +++ b/Alc/backends/portaudio.c @@ -419,6 +419,13 @@ static ALCuint pa_available_samples(ALCdevice *device) } +static ALint64 pa_get_latency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs pa_funcs = { pa_open_playback, pa_close_playback, @@ -430,7 +437,8 @@ static const BackendFuncs pa_funcs = { pa_start_capture, pa_stop_capture, pa_capture_samples, - pa_available_samples + pa_available_samples, + pa_get_latency }; ALCboolean alc_pa_init(BackendFuncs *func_list) diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c index 2621e334..87a04946 100644 --- a/Alc/backends/pulseaudio.c +++ b/Alc/backends/pulseaudio.c @@ -66,6 +66,7 @@ MAKE_FUNC(pa_stream_is_corked); MAKE_FUNC(pa_stream_cork); MAKE_FUNC(pa_stream_is_suspended); MAKE_FUNC(pa_stream_get_device_name); +MAKE_FUNC(pa_stream_get_latency); MAKE_FUNC(pa_path_get_filename); MAKE_FUNC(pa_get_binary_name); MAKE_FUNC(pa_threaded_mainloop_free); @@ -138,6 +139,7 @@ MAKE_FUNC(pa_stream_begin_write); #define pa_stream_cork ppa_stream_cork #define pa_stream_is_suspended ppa_stream_is_suspended #define pa_stream_get_device_name ppa_stream_get_device_name +#define pa_stream_get_latency ppa_stream_get_latency #define pa_path_get_filename ppa_path_get_filename #define pa_get_binary_name ppa_get_binary_name #define pa_threaded_mainloop_free ppa_threaded_mainloop_free @@ -273,6 +275,7 @@ static ALCboolean pulse_load(void) LOAD_FUNC(pa_stream_cork); LOAD_FUNC(pa_stream_is_suspended); LOAD_FUNC(pa_stream_get_device_name); + LOAD_FUNC(pa_stream_get_latency); LOAD_FUNC(pa_path_get_filename); LOAD_FUNC(pa_get_binary_name); LOAD_FUNC(pa_threaded_mainloop_free); @@ -1375,6 +1378,23 @@ static ALCuint pulse_available_samples(ALCdevice *device) } +static ALint64 pulse_get_latency(ALCdevice *device) +{ + pulse_data *data = device->ExtraData; + pa_usec_t latency = 0; + int neg; + + if(pa_stream_get_latency(data->stream, &latency, &neg) == 0) + { + if(neg) + latency = 0; + return (ALint64)minu64(latency, (((ALuint64)0x7fffffff << 32)|0xffffffff)/1000) * 1000; + } + ERR("Failed to get stream latency!\n"); + return 0; +} + + static const BackendFuncs pulse_funcs = { pulse_open_playback, pulse_close_playback, @@ -1386,7 +1406,8 @@ static const BackendFuncs pulse_funcs = { pulse_start_capture, pulse_stop_capture, pulse_capture_samples, - pulse_available_samples + pulse_available_samples, + pulse_get_latency }; ALCboolean alc_pulse_init(BackendFuncs *func_list) diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c index 1d1c512c..c1dbc1a6 100644 --- a/Alc/backends/sndio.c +++ b/Alc/backends/sndio.c @@ -252,6 +252,13 @@ static void sndio_stop_playback(ALCdevice *device) } +static ALint64 sndio_get_latency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs sndio_funcs = { sndio_open_playback, sndio_close_playback, @@ -263,7 +270,8 @@ static const BackendFuncs sndio_funcs = { NULL, NULL, NULL, - NULL + NULL, + sndio_get_latency }; ALCboolean alc_sndio_init(BackendFuncs *func_list) diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c index 215e7209..4be32a50 100644 --- a/Alc/backends/solaris.c +++ b/Alc/backends/solaris.c @@ -236,6 +236,13 @@ static void solaris_stop_playback(ALCdevice *device) } +static ALint64 solaris_get_latency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs solaris_funcs = { solaris_open_playback, solaris_close_playback, @@ -247,7 +254,8 @@ static const BackendFuncs solaris_funcs = { NULL, NULL, NULL, - NULL + NULL, + solaris_get_latency }; ALCboolean alc_solaris_init(BackendFuncs *func_list) diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 47db5460..fb118ee8 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -322,6 +322,14 @@ static void wave_stop_playback(ALCdevice *device) } +static ALint64 wave_get_latency(ALCdevice *device) +{ + /* FIXME: time until next update + "safe" offset */ + (void)device; + return 0; +} + + static const BackendFuncs wave_funcs = { wave_open_playback, wave_close_playback, @@ -333,7 +341,8 @@ static const BackendFuncs wave_funcs = { NULL, NULL, NULL, - NULL + NULL, + wave_get_latency }; ALCboolean alc_wave_init(BackendFuncs *func_list) diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index b7c637d6..ecd76e52 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -705,6 +705,13 @@ static ALCuint WinMMAvailableSamples(ALCdevice *Device) } +static ALint64 WinMMGetLatency(ALCdevice *device) +{ + (void)device; + return 0; +} + + static const BackendFuncs WinMMFuncs = { WinMMOpenPlayback, WinMMClosePlayback, @@ -716,7 +723,8 @@ static const BackendFuncs WinMMFuncs = { WinMMStartCapture, WinMMStopCapture, WinMMCaptureSamples, - WinMMAvailableSamples + WinMMAvailableSamples, + WinMMGetLatency }; ALCboolean alcWinMMInit(BackendFuncs *FuncList) -- cgit v1.2.3