From: Mike Brady Date: Mon, 17 Jun 2019 18:43:23 +0000 (+0100) Subject: refine the selection of precision timing to be allowed only if the device is a real... X-Git-Tag: 3.3.2~4^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7013b0cc3d1fe9edead493f0a6f97d3a0ca44ffe;p=thirdparty%2Fshairport-sync.git refine the selection of precision timing to be allowed only if the device is a real hardware device --- diff --git a/audio_alsa.c b/audio_alsa.c index 26a0014d..2ef94661 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -175,10 +175,14 @@ int (*delay_and_status)(snd_pcm_state_t *state, snd_pcm_sframes_t *delay, enum y int precision_delay_available() { if (precision_delay_available_status == YNDK_DONT_KNOW) { - // At present, the only criterion as to whether precision delay is available + // this is very crude -- if the device is a hardware device, then it's assumed the delay is precise + const char *output_device_name = snd_pcm_name(alsa_handle); + int is_a_real_hardware_device = (strstr(output_device_name,"hw:") == output_device_name); + + // The criteria as to whether precision delay is available // is whether the device driver returns non-zero update timestamps - // If it does, it is considered precision delay is available - // Otherwise, it's considered to be unavailable + // If it does, and the device is a hardware device (i.e. its name begins with "hw:0"), + // it is considered that precision delay is available. Otherwise, it's considered to be unavailable. // To test, we play a silence buffer (fairly large to avoid underflow) // and then we check the delay return. It will tell us if it @@ -213,12 +217,16 @@ int precision_delay_available() { int ret = precision_delay_and_status(&state, &delay, &uses_update_timestamps); // debug(3,"alsa: precision_delay_available asking for delay and status with a return status of %d, a delay of %ld and a uses_update_timestamps of %d.", ret, delay, uses_update_timestamps); if (ret == 0) { - if (uses_update_timestamps == YNDK_YES) { + if ((uses_update_timestamps == YNDK_YES) && (is_a_real_hardware_device)) { precision_delay_available_status = YNDK_YES; debug(2,"alsa: precision delay timing is available."); } else { - precision_delay_available_status = YNDK_NO; - debug(2,"alsa: precision delay timing is not available."); + if ((uses_update_timestamps == YNDK_YES) && (!is_a_real_hardware_device)) { + debug(2,"alsa: precision delay timing is not available because it's not definitely a hardware device."); + } else { + debug(2,"alsa: precision delay timing is not available."); + } + precision_delay_available_status = YNDK_NO; } } } @@ -1435,14 +1443,13 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay, // user information if (update_timestamp_ns == 0) { if (delay_type_notified != 1) { - inform("Note: the alsa output device \"%s\" is not capable of high precision delay timing.", snd_pcm_name(alsa_handle)); - debug(1,"alsa: delay_and_status must use snd_pcm_delay() to calculate delay"); + debug(2,"alsa: update timestamps unavailable"); delay_type_notified = 1; } } else { // diagnostic if (delay_type_notified != 0) { - debug(2,"alsa: delay_and_status using snd_pcm_status_get_delay() to calculate delay"); + debug(2,"alsa: update timestamps available"); delay_type_notified = 0; } }