static int snd_func_iops(snd_config_t **dst, snd_config_t *root, snd_config_t *src, snd_config_t *private_data, int op) { snd_config_t *n; snd_config_iterator_t i, next; const char *id; char *res = NULL; long result = 0, val; int idx = 0, err, hit; err = snd_config_search(src, "integers", &n); if (err < 0) { SNDERR("field integers not found"); goto __error; } err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating integers"); goto __error; } do { hit = 0; snd_config_for_each(i, next, n) { snd_config_t *n = snd_config_iterator_entry(i); const char *id; long i; if (snd_config_get_id(n, &id) < 0) continue; err = safe_strtol(id, &i); if (err < 0) { SNDERR("id of field %s is not an integer", id); err = -EINVAL; goto __error; } if (i == idx) { idx++; err = snd_config_get_integer(n, &val); if (err < 0) { SNDERR("invalid integer for id %s", id); err = -EINVAL; goto __error; } switch (op) { case 0: result += val; break; case 1: result *= val; break; } hit = 1; } } } while (hit); err = snd_config_get_id(src, &id); if (err >= 0) err = snd_config_imake_integer(dst, id, result); free(res); __error: return err; }
/** * \brief Returns an integer environment value. * \param dst The function puts the handle to the result configuration node * (with type integer) at the address specified by \p dst. * \param root Handle to the root source node. * \param src Handle to the source node, with definitions for \c vars and * \c default. * \param private_data Handle to the \c private_data node. * \return Zero if successful, otherwise a negative error code. * * Example: \code { @func igetenv vars [ MY_DEVICE DEVICE D ] default 0 } \endcode */ int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, snd_config_t *private_data) { snd_config_t *d; const char *str, *id; int err; long v; err = snd_func_getenv(&d, root, src, private_data); if (err < 0) return err; err = snd_config_get_string(d, &str); if (err < 0) { snd_config_delete(d); return err; } err = safe_strtol(str, &v); if (err < 0) { snd_config_delete(d); return err; } snd_config_delete(d); err = snd_config_get_id(src, &id); if (err < 0) return err; err = snd_config_imake_integer(dst, id, v); if (err < 0) 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; }