From: Jaroslav Kysela Date: Fri, 7 Dec 2001 14:12:35 +0000 (+0000) Subject: Added snd_config_update_r, snd_config_update_free functions X-Git-Tag: android-x86-9.0-r1~2601 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=76c8029e2b5a99bd31dea7dc9bbb95e19a8dd2e5;p=android-x86%2Fexternal-alsa-lib.git Added snd_config_update_r, snd_config_update_free functions --- diff --git a/include/conf.h b/include/conf.h index f525dfa8..6c868f3d 100644 --- a/include/conf.h +++ b/include/conf.h @@ -61,6 +61,8 @@ typedef enum _snd_config_type { typedef struct _snd_config snd_config_t; /** Config compound iterator */ typedef struct _snd_config_iterator *snd_config_iterator_t; +/** Config private update structure */ +typedef struct _snd_config_update snd_config_update_t; extern snd_config_t *snd_config; @@ -69,6 +71,8 @@ int snd_config_top(snd_config_t **config); int snd_config_load(snd_config_t *config, snd_input_t *in); int snd_config_save(snd_config_t *config, snd_output_t *out); int snd_config_update(void); +int snd_config_update_r(snd_config_t **top, snd_config_update_t **update, const char *path); +int snd_config_update_free(snd_config_update_t *update); int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result); diff --git a/src/conf.c b/src/conf.c index ecd1b96d..6e554b01 100644 --- a/src/conf.c +++ b/src/conf.c @@ -338,6 +338,7 @@ func.remove_first_char { #include #include #include +#include #include "local.h" #ifndef DOC_HIDDEN @@ -2205,17 +2206,22 @@ int snd_config_search_alias_hooks(snd_config_t *config, #define ALSA_CONFIG_PATH_DEFAULT DATADIR "/alsa/alsa.conf" /** \ingroup Config - * Config top node */ + * Config top node (global configuration) */ snd_config_t *snd_config = NULL; -static struct finfo { +struct finfo { char *name; dev_t dev; ino_t ino; time_t mtime; -} *files_info = NULL; +}; + +struct _snd_config_update { + unsigned int count; + struct finfo *finfo; +}; -static unsigned int files_info_count = 0; +static snd_config_update_t *snd_config_global_update = NULL; static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data) { @@ -2536,29 +2542,40 @@ SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VER #endif /** - * \brief Update #snd_config rereading (if needed) global configuration files. + * \brief Update #snd_config rereading (if needed) configuration files. + * \param top Top node + * \param update Private update information + * \param cfgs Configuration files in list delimited with ':', if NULL -> default global + * configuration file is used - "/usr/share/alsa/alsa.conf". * \return non-negative value on success, otherwise a negative error code * \retval 0 no action is needed * \retval 1 tree has been rebuild * * The global configuration files are specified in environment variable ALSA_CONFIG_PATH. - * If it is not set the default value is "/usr/share/alsa/alsa.conf". * * Warning: If config tree is reread all the string pointer and config - * node handle previously obtained from this tree become invalid + * node handle previously obtained from this tree become invalid. */ -int snd_config_update() +int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs) { int err; - char *configs, *c; + const char *configs, *c; unsigned int k; wordexp_t we; size_t l; - struct finfo *fi = NULL; - unsigned int fi_count; - configs = getenv(ALSA_CONFIG_PATH_VAR); - if (!configs) - configs = ALSA_CONFIG_PATH_DEFAULT; + snd_config_update_t *local; + snd_config_update_t *update; + snd_config_t *top; + + assert(_top && _update); + top = *_top; + update = *_update; + configs = cfgs; + if (!configs) { + configs = getenv(ALSA_CONFIG_PATH_VAR); + if (!configs) + configs = ALSA_CONFIG_PATH_DEFAULT; + } for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) { c += l; k++; @@ -2566,12 +2583,19 @@ int snd_config_update() break; c++; } - fi_count = k; - if (fi_count == 0) + if (k == 0) { + local = NULL; goto _reread; - fi = calloc(fi_count, sizeof(*fi)); - if (!fi) + } + local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t)); + if (!local) + return -ENOMEM; + local->count = k; + local->finfo = calloc(local->count, sizeof(struct finfo)); + if (!local->finfo) { + free(local); return -ENOMEM; + } for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) { char name[l + 1]; memcpy(name, c, l); @@ -2589,9 +2613,9 @@ int snd_config_update() err = -EINVAL; goto _end; } - fi[k].name = strdup(we.we_wordv[0]); + local->finfo[k].name = strdup(we.we_wordv[0]); wordfree(&we); - if (!fi[k].name) { + if (!local->finfo[k].name) { err = -ENOMEM; goto _end; } @@ -2601,81 +2625,132 @@ int snd_config_update() break; c++; } - for (k = 0; k < fi_count; ++k) { + for (k = 0; k < local->count; ++k) { struct stat st; - if (stat(fi[k].name, &st) >= 0) { - fi[k].dev = st.st_dev; - fi[k].ino = st.st_ino; - fi[k].mtime = st.st_mtime; + struct finfo *lf = &local->finfo[k]; + if (stat(lf->name, &st) >= 0) { + lf->dev = st.st_dev; + lf->ino = st.st_ino; + lf->mtime = st.st_mtime; } else { - memmove(&fi[k], &fi[k+1], sizeof(*fi) * (fi_count - k - 1)); + memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1)); k--; - fi_count--; + local->count--; } } - if (!files_info) + if (!update) goto _reread; - if (fi_count != files_info_count) + if (local->count != update->count) goto _reread; - for (k = 0; k < fi_count; ++k) { - if (strcmp(fi[k].name, files_info[k].name) != 0 || - fi[k].dev != files_info[k].dev || - fi[k].ino != files_info[k].ino || - fi[k].mtime != files_info[k].mtime) + for (k = 0; k < local->count; ++k) { + struct finfo *lf = &local->finfo[k]; + struct finfo *uf = &update->finfo[k]; + if (strcmp(lf->name, uf->name) != 0 || + lf->dev != uf->dev || + lf->ino != uf->ino || + lf->mtime != uf->mtime) goto _reread; } err = 0; _end: - if (err < 0 && snd_config) { - snd_config_delete(snd_config); - snd_config = NULL; + if (err < 0) { + if (top) { + snd_config_delete(top); + *_top = NULL; + } + if (update) { + snd_config_update_free(update); + *_update = NULL; + } } - for (k = 0; k < fi_count; ++k) - free(fi[k].name); - if (fi) - free(fi); + if (local) + snd_config_update_free(local); return err; _reread: - if (files_info) { - for (k = 0; k < files_info_count; ++k) - free(files_info[k].name); - free(files_info); - files_info = NULL; - files_info_count = 0; - } - if (snd_config) { - snd_config_delete(snd_config); - snd_config = NULL; - } - err = snd_config_top(&snd_config); + *_top = NULL; + *_update = NULL; + if (update) { + snd_config_update_free(update); + update = NULL; + } + if (top) { + snd_config_delete(top); + top = NULL; + } + err = snd_config_top(&top); if (err < 0) goto _end; - for (k = 0; k < fi_count; ++k) { + if (!local) + goto _skip; + for (k = 0; k < local->count; ++k) { snd_input_t *in; - err = snd_input_stdio_open(&in, fi[k].name, "r"); + err = snd_input_stdio_open(&in, local->finfo[k].name, "r"); if (err >= 0) { - err = snd_config_load(snd_config, in); + err = snd_config_load(top, in); snd_input_close(in); if (err < 0) { - SNDERR("%s may be old or corrupted: consider to remove or fix it", fi[k].name); + SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name); goto _end; } } else { - SNDERR("cannot access file %s", fi[k].name); + SNDERR("cannot access file %s", local->finfo[k].name); } } - err = snd_config_hooks(snd_config, NULL); + _skip: + err = snd_config_hooks(top, NULL); if (err < 0) { SNDERR("hooks failed, removing configuration"); goto _end; } - files_info = fi; - files_info_count = fi_count; + *_top = top; + *_update = local; return 1; } +static pthread_mutex_t snd_config_update_mutex = PTHREAD_MUTEX_INITIALIZER; + +/** + * \brief Update #snd_config rereading (if needed) global configuration files. + * \return non-negative value on success, otherwise a negative error code + * \retval 0 no action is needed + * \retval 1 tree has been rebuild + * + * The global configuration files are specified in environment variable ALSA_CONFIG_PATH. + * If it is not set the default value is "/usr/share/alsa/alsa.conf". + * + * Warning: If config tree is reread all the string pointer and config + * node handle previously obtained from this tree become invalid. + */ +int snd_config_update(void) +{ + int err; + + pthread_mutex_lock(&snd_config_update_mutex); + err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL); + pthread_mutex_unlock(&snd_config_update_mutex); + return err; +} + +/** + * \brief Free private update structure + * \param update private update structure to free + * \return non-negative value on success, otherwise a negative error code + */ +int snd_config_update_free(snd_config_update_t *update) +{ + int k; + + assert(update); + assert(update->count > 0 && update->finfo); + for (k = 0; k < update->count; k++) + free(update->finfo[k].name); + if (update->finfo) + free(update->finfo); + free(update); + return 0; +} /** * \brief Return an iterator pointing to first leaf of a compound config node