static int snd_config_compound_add(snd_config_t *father, const char *id, int join, snd_config_t **node) { int err; snd_config_t *leaf; err = snd_config_make_compound(&leaf, id, join); if (err < 0) return err; err = snd_config_add(father, leaf); if (err < 0) { snd_config_delete(leaf); return err; } *node = leaf; return 0; }
static int snd_config_integer64_add(snd_config_t *father, char *id, long long integer) { int err; snd_config_t *leaf; err = snd_config_make_integer64(&leaf, id); if (err < 0) return err; err = snd_config_add(father, leaf); if (err < 0) { snd_config_delete(leaf); return err; } err = snd_config_set_integer64(leaf, integer); if (err < 0) { snd_config_delete(leaf); return err; } return 0; }
static int snd_config_string_add(snd_config_t *father, const char *id, const char *string) { int err; snd_config_t *leaf; err = snd_config_make_string(&leaf, id); if (err < 0) return err; err = snd_config_add(father, leaf); if (err < 0) { snd_config_delete(leaf); return err; } err = snd_config_set_string(leaf, string); if (err < 0) { snd_config_delete(leaf); return err; } return 0; }
/* Work around PulseAudio ALSA plugin bug where the PA server forces a higher than requested latency, but the plugin does not update its (and ALSA's) internal state to reflect that, leading to an immediate underrun situation. Inspired by WINE's make_handle_underrun_config. Reference: http://mailman.alsa-project.org/pipermail/alsa-devel/2012-July/05 */ static snd_config_t * init_local_config_with_workaround(char const * pcm_name) { int r; snd_config_t * lconf; snd_config_t * pcm_node; snd_config_t * node; char const * string; char node_name[64]; lconf = NULL; if (snd_config == NULL) { return NULL; } r = snd_config_copy(&lconf, snd_config); if (r < 0) { return NULL; } do { r = snd_config_search_definition(lconf, "pcm", pcm_name, &pcm_node); if (r < 0) { break; } r = snd_config_get_id(pcm_node, &string); if (r < 0) { break; } r = snprintf(node_name, sizeof(node_name), "pcm.%s", string); if (r < 0 || r > (int) sizeof(node_name)) { break; } r = snd_config_search(lconf, node_name, &pcm_node); if (r < 0) { break; } /* If this PCM has a slave, walk the slave configurations until we reach the bottom. */ while ((node = get_slave_pcm_node(lconf, pcm_node)) != NULL) { pcm_node = node; } /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */ r = snd_config_search(pcm_node, "type", &node); if (r < 0) { break; } r = snd_config_get_string(node, &string); if (r < 0) { break; } if (strcmp(string, "pulse") != 0) { break; } /* Don't clobber an explicit existing handle_underrun value, set it only if it doesn't already exist. */ r = snd_config_search(pcm_node, "handle_underrun", &node); if (r != -ENOENT) { break; } /* Disable pcm_pulse's asynchronous underrun handling. */ r = snd_config_imake_integer(&node, "handle_underrun", 0); if (r < 0) { break; } r = snd_config_add(pcm_node, node); if (r < 0) { break; } return lconf; } while (0); snd_config_delete(lconf); return NULL; }
/* Work around PulseAudio ALSA plugin bug where the PA server forces a higher than requested latency, but the plugin does not update its (and ALSA's) internal state to reflect that, leading to an immediate underrun situation. Inspired by WINE's make_handle_underrun_config. Reference: http://mailman.alsa-project.org/pipermail/alsa-devel/2012-July/053391.html From Mozilla https://github.com/kinetiknz/cubeb/blob/1aa0058d0729eb85505df104cd1ac072432c6d24/src/cubeb_alsa.c */ static snd_config_t *init_local_config_with_workaround(ao_device *device, char const *name){ char pcm_node_name[80]; int r; snd_config_t * lconf; snd_config_t * device_node; snd_config_t * type_node; snd_config_t * node; char const * type_string; lconf = NULL; snprintf(pcm_node_name,80,"pcm.%s",name); if (snd_config == NULL) snd_config_update(); r = snd_config_copy(&lconf, snd_config); if(r<0){ return NULL; } r = snd_config_search(lconf, pcm_node_name, &device_node); if (r != 0) { snd_config_delete(lconf); return NULL; } /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */ r = snd_config_search(device_node, "type", &type_node); if (r != 0) { snd_config_delete(lconf); return NULL; } r = snd_config_get_string(type_node, &type_string); if (r != 0) { snd_config_delete(lconf); return NULL; } if (strcmp(type_string, "pulse") != 0) { snd_config_delete(lconf); return NULL; } /* Don't clobber an explicit existing handle_underrun value, set it only if it doesn't already exist. */ r = snd_config_search(device_node, "handle_underrun", &node); if (r != -ENOENT) { snd_config_delete(lconf); return NULL; } r = snd_config_imake_integer(&node, "handle_underrun", 0); if (r != 0) { snd_config_delete(lconf); return NULL; } r = snd_config_add(device_node, node); if (r != 0) { snd_config_delete(lconf); return NULL; } adebug("PulseAudio ALSA-emulation detected: disabling underrun detection\n"); return lconf; }