diff options
author | Jaroslav Kysela <perex@perex.cz> | 2010-10-13 11:48:52 +0200 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2010-10-13 11:48:52 +0200 |
commit | e8208666379e10bbd56365b0a6d17f3daab730e3 (patch) | |
tree | 676cbb81e317b0d4850552942fcbf4b246ae47c2 | |
parent | 3a3439450864c8706e4e20d392fd43ecf935153f (diff) | |
download | alsa-lib-e8208666379e10bbd56365b0a6d17f3daab730e3.tar.gz |
ucm: implemented card list feature
- also added some test files to test/ucm tree
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r-- | src/ucm/main.c | 12 | ||||
-rw-r--r-- | src/ucm/parser.c | 142 | ||||
-rw-r--r-- | src/ucm/ucm_local.h | 1 | ||||
-rw-r--r-- | src/ucm/utils.c | 5 | ||||
-rw-r--r-- | test/ucm/anothercard/anothercard.conf | 1 | ||||
-rw-r--r-- | test/ucm/testcard1/testcard1.conf | 0 |
6 files changed, 134 insertions, 27 deletions
diff --git a/src/ucm/main.c b/src/ucm/main.c index 88389764..e233f414 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -562,16 +562,6 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr) } /** - * \brief Get list of cards in pair cardname+comment - * \param list Returned list - * \return Number of list entries if success, otherwise a negative error code - */ -static int get_card_list(const char **list[]) -{ - return -ENXIO; /* Not Yet Implemented */ -} - -/** * \brief Get list of verbs in pair verbname+comment * \param list Returned list * \param verbname For verb (NULL = current) @@ -780,7 +770,7 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr, int err; if (uc_mgr == NULL || identifier == NULL) - return get_card_list(list); + return uc_mgr_scan_master_configs(list); pthread_mutex_lock(&uc_mgr->mutex); if (strcmp(identifier, "_verbs") == 0) err = get_verb_list(uc_mgr, list); diff --git a/src/ucm/parser.c b/src/ucm/parser.c index e540c20d..4e2a9d74 100644 --- a/src/ucm/parser.c +++ b/src/ucm/parser.c @@ -31,6 +31,7 @@ */ #include "ucm_local.h" +#include <dirent.h> static int parse_sequence(snd_use_case_mgr_t *uc_mgr, struct list_head *base, @@ -827,7 +828,7 @@ static int parse_master_section(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg, } /* - * parse and execute controls + * parse controls */ static int parse_controls(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) { @@ -851,6 +852,8 @@ static int parse_controls(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) * #Example master file for blah sound card * #By Joe Blogs <joe@bloggs.org> * + * Comment "Nice Abstracted Soundcard" + * * # The file is divided into Use case sections. One section per use case verb. * * SectionUseCase."Voice Call" { @@ -882,7 +885,8 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) { snd_config_iterator_t i, next; snd_config_t *n; - int ret; + const char *id; + int err; if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { uc_error("compound type expected for master file"); @@ -891,26 +895,35 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) /* parse master config sections */ snd_config_for_each(i, next, cfg) { - const char *id; + n = snd_config_iterator_entry(i); if (snd_config_get_id(n, &id) < 0) continue; + if (strcmp(id, "Comment") == 0) { + err = parse_string(n, &uc_mgr->comment); + if (err < 0) { + uc_error("error: failed to get master comment"); + return err; + } + continue; + } + /* find use case section and parse it */ if (strcmp(id, "SectionUseCase") == 0) { - ret = parse_compound(uc_mgr, n, + err = parse_compound(uc_mgr, n, parse_master_section, NULL, NULL); - if (ret < 0) - return ret; + if (err < 0) + return err; continue; } /* find default control values section and parse it */ if (strcmp(id, "SectionDefaults") == 0) { - ret = parse_controls(uc_mgr, n); - if (ret < 0) - return ret; + err = parse_controls(uc_mgr, n); + if (err < 0) + return err; continue; } uc_error("uknown master file field %s", id); @@ -918,25 +931,39 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) return 0; } -/* load master use case file for sound card */ -int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr) +/** The name of the environment variable containing the UCM directory */ +#define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM" + +static int load_master_config(const char *card_name, snd_config_t **cfg) { char filename[MAX_FILE]; - snd_config_t *cfg; + char *env = getenv(ALSA_CONFIG_UCM_VAR); int err; snprintf(filename, sizeof(filename)-1, - "%s/%s/%s.conf", ALSA_USE_CASE_DIR, - uc_mgr->card_name, uc_mgr->card_name); + "%s/%s/%s.conf", env ? env : ALSA_USE_CASE_DIR, + card_name, card_name); filename[MAX_FILE-1] = '\0'; - err = uc_mgr_config_load(filename, &cfg); + err = uc_mgr_config_load(filename, cfg); if (err < 0) { uc_error("error: could not parse configuration for card %s", - uc_mgr->card_name); + card_name); return err; } + return 0; +} + +/* load master use case file for sound card */ +int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr) +{ + snd_config_t *cfg; + int err; + + err = load_master_config(uc_mgr->card_name, &cfg); + if (err < 0) + return err; err = parse_master_file(uc_mgr, cfg); snd_config_delete(cfg); if (err < 0) @@ -944,3 +971,86 @@ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr) return err; } + +static int filename_filter(const struct dirent *dirent) +{ + if (dirent == NULL) + return 0; + if (dirent->d_type == DT_DIR) { + if (dirent->d_name[0] == '.') { + if (dirent->d_name[1] == '\0') + return 0; + if (dirent->d_name[1] == '.' && + dirent->d_name[2] == '\0') + return 0; + } + return 1; + } + return 0; +} + +/* scan all cards and comments */ +int uc_mgr_scan_master_configs(const char **_list[]) +{ + char filename[MAX_FILE]; + char *env = getenv(ALSA_CONFIG_UCM_VAR); + const char **list; + snd_config_t *cfg, *c; + int i, cnt, err; + struct dirent **namelist; + + snprintf(filename, sizeof(filename)-1, + "%s", env ? env : ALSA_USE_CASE_DIR); + filename[MAX_FILE-1] = '\0'; + + err = scandir(filename, &namelist, filename_filter, alphasort); + if (err < 0) { + err = -errno; + uc_error("error: could not scan directory %s: %s", + filename, strerror(-err)); + return err; + } + cnt = err; + + list = calloc(1, cnt * 2 * sizeof(char *)); + if (list == NULL) { + err = -ENOMEM; + goto __err; + } + + for (i = 0; i < cnt; i++) { + err = load_master_config(namelist[i]->d_name, &cfg); + if (err < 0) + goto __err; + err = snd_config_search(cfg, "Comment", &c); + if (err >= 0) { + err = parse_string(c, (char **)&list[i*2+1]); + if (err < 0) { + snd_config_delete(cfg); + goto __err; + } + } + snd_config_delete(cfg); + list[i * 2] = strdup(namelist[i]->d_name); + if (list[i * 2] == NULL) { + err = -ENOMEM; + goto __err; + } + } + err = cnt * 2; + + __err: + for (i = 0; i < cnt; i++) { + free(namelist[i]); + if (err < 0) { + free((void *)list[i * 2]); + free((void *)list[i * 2 + 1]); + } + } + free(namelist); + + if (err >= 0) + *_list = list; + + return err; +} diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h index 06a1e5f6..7dae5b6a 100644 --- a/src/ucm/ucm_local.h +++ b/src/ucm/ucm_local.h @@ -193,6 +193,7 @@ void uc_mgr_stdout(const char *fmt, ...); int uc_mgr_config_load(const char *file, snd_config_t **cfg); int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr); +int uc_mgr_scan_master_configs(const char **_list[]); void uc_mgr_free_sequence_element(struct sequence_element *seq); void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr); diff --git a/src/ucm/utils.c b/src/ucm/utils.c index 83926da3..0f8207e8 100644 --- a/src/ucm/utils.c +++ b/src/ucm/utils.c @@ -57,8 +57,13 @@ int uc_mgr_config_load(const char *file, snd_config_t **cfg) int err; fp = fopen(file, "r"); + if (fp == NULL) { + err = -errno; + goto __err; + } err = snd_input_stdio_attach(&in, fp, 1); if (err < 0) { + __err: uc_error("could not open configuration file %s", file); return err; } diff --git a/test/ucm/anothercard/anothercard.conf b/test/ucm/anothercard/anothercard.conf new file mode 100644 index 00000000..3d9ed7de --- /dev/null +++ b/test/ucm/anothercard/anothercard.conf @@ -0,0 +1 @@ +Comment "Another Card" diff --git a/test/ucm/testcard1/testcard1.conf b/test/ucm/testcard1/testcard1.conf new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/ucm/testcard1/testcard1.conf |