ucm: debug parser

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2010-10-26 14:26:46 +02:00
parent e820866637
commit e4083a1182
5 changed files with 274 additions and 160 deletions

View file

@ -33,6 +33,9 @@
#include "ucm_local.h" #include "ucm_local.h"
#include <dirent.h> #include <dirent.h>
/** The name of the environment variable containing the UCM directory */
#define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM"
static int parse_sequence(snd_use_case_mgr_t *uc_mgr, static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
struct list_head *base, struct list_head *base,
snd_config_t *cfg); snd_config_t *cfg);
@ -70,43 +73,37 @@ static int parse_transition(snd_use_case_mgr_t *uc_mgr,
if (snd_config_get_id(cfg, &id) < 0) if (snd_config_get_id(cfg, &id) < 0)
return -EINVAL; return -EINVAL;
tseq = calloc(1, sizeof(*tseq));
if (tseq == NULL)
return -ENOMEM;
INIT_LIST_HEAD(&tseq->transition_list);
tseq->name = strdup(id);
if (tseq->name == NULL) {
free(tseq);
return -ENOMEM;
}
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
uc_error("compound type expected for %s", id); uc_error("compound type expected for %s", id);
err = -EINVAL; return -EINVAL;
goto __err;
} }
/* parse master config sections */
snd_config_for_each(i, next, cfg) { snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i); n = snd_config_iterator_entry(i);
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { if (snd_config_get_id(n, &id) < 0)
uc_error("compound type expected for %s", id); return -EINVAL;
err = -EINVAL;
goto __err; tseq = calloc(1, sizeof(*tseq));
if (tseq == NULL)
return -ENOMEM;
INIT_LIST_HEAD(&tseq->transition_list);
tseq->name = strdup(id);
if (tseq->name == NULL) {
free(tseq);
return -ENOMEM;
} }
err = parse_sequence(uc_mgr, &tseq->transition_list, n); err = parse_sequence(uc_mgr, &tseq->transition_list, n);
if (err < 0) if (err < 0) {
uc_mgr_free_transition_element(tseq);
return err; return err;
} }
list_add(&tseq->list, tlist); list_add(&tseq->list, tlist);
}
return 0; return 0;
__err:
free(tseq->name);
free(tseq);
return err;
} }
/* /*
@ -128,7 +125,7 @@ static int parse_compound(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
uc_error("compound type expected for %s", id); uc_error("compound type expected for %s", id);
return -EINVAL; return -EINVAL;
} }
/* parse master config sections */ /* parse compound */
snd_config_for_each(i, next, cfg) { snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i); n = snd_config_iterator_entry(i);
@ -145,6 +142,47 @@ static int parse_compound(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
return 0; return 0;
} }
/*
* Parse transition
*/
static int parse_supported_device(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
struct list_head *dlist,
snd_config_t *cfg)
{
struct dev_list *sdev;
const char *id;
snd_config_iterator_t i, next;
snd_config_t *n;
int err;
if (snd_config_get_id(cfg, &id) < 0)
return -EINVAL;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
uc_error("compound type expected for %s", id);
return -EINVAL;
}
snd_config_for_each(i, next, cfg) {
n = snd_config_iterator_entry(i);
if (snd_config_get_id(n, &id) < 0)
return -EINVAL;
sdev = calloc(1, sizeof(struct dev_list));
if (sdev == NULL)
return -ENOMEM;
err = parse_string(n, &sdev->name);
if (err < 0) {
free(sdev);
return err;
}
list_add(&sdev->list, dlist);
}
return 0;
}
/* /*
* Parse sequences. * Parse sequences.
* *
@ -163,58 +201,60 @@ static int parse_sequence(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
snd_config_t *cfg) snd_config_t *cfg)
{ {
struct sequence_element *curr; struct sequence_element *curr;
snd_config_iterator_t i, next, j, next2; snd_config_iterator_t i, next;
snd_config_t *n, *n2; snd_config_t *n;
int err; int err;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
uc_error("error: compound is expected for sequence definition");
return -EINVAL;
}
snd_config_for_each(i, next, cfg) { snd_config_for_each(i, next, cfg) {
const char *id;
n = snd_config_iterator_entry(i); n = snd_config_iterator_entry(i);
snd_config_for_each(j, next2, n) { err = snd_config_get_id(n, &id);
const char *id; if (err < 0)
n2 = snd_config_iterator_entry(i); continue;
err = snd_config_get_id(n2, &id);
if (err < 0)
continue;
/* alloc new sequence element */ /* alloc new sequence element */
curr = calloc(1, sizeof(struct sequence_element)); curr = calloc(1, sizeof(struct sequence_element));
if (curr == NULL) if (curr == NULL)
return -ENOMEM; return -ENOMEM;
list_add_tail(&curr->list, base); list_add_tail(&curr->list, base);
if (strcmp(id, "cset") == 0) { if (strcmp(id, "cset") == 0) {
curr->type = SEQUENCE_ELEMENT_TYPE_CSET; curr->type = SEQUENCE_ELEMENT_TYPE_CSET;
err = parse_string(n2, &curr->data.cset); err = parse_string(n, &curr->data.cset);
if (err < 0) { if (err < 0) {
uc_error("error: cset requires a string!"); uc_error("error: cset requires a string!");
return err; return err;
}
continue;
} }
continue;
if (strcmp(id, "usleep") == 0) {
curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
err = snd_config_get_integer(n2, &curr->data.sleep);
if (err < 0) {
uc_error("error: usleep requires integer!");
return err;
}
continue;
}
if (strcmp(id, "exec") == 0) {
curr->type = SEQUENCE_ELEMENT_TYPE_EXEC;
err = parse_string(n2, &curr->data.exec);
if (err < 0) {
uc_error("error: exec requires a string!");
return err;
}
continue;
}
list_del(&curr->list);
uc_mgr_free_sequence_element(curr);
} }
if (strcmp(id, "usleep") == 0) {
curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
err = snd_config_get_integer(n, &curr->data.sleep);
if (err < 0) {
uc_error("error: usleep requires integer!");
return err;
}
continue;
}
if (strcmp(id, "exec") == 0) {
curr->type = SEQUENCE_ELEMENT_TYPE_EXEC;
err = parse_string(n, &curr->data.exec);
if (err < 0) {
uc_error("error: exec requires a string!");
return err;
}
continue;
}
list_del(&curr->list);
uc_mgr_free_sequence_element(curr);
} }
return 0; return 0;
@ -237,65 +277,66 @@ static int parse_value(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
snd_config_t *cfg) snd_config_t *cfg)
{ {
struct ucm_value *curr; struct ucm_value *curr;
snd_config_iterator_t i, next, j, next2; snd_config_iterator_t i, next;
snd_config_t *n, *n2; snd_config_t *n;
long l; long l;
long long ll; long long ll;
double d; double d;
snd_config_type_t type; snd_config_type_t type;
int err; int err;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
uc_error("error: compound is expected for value definition");
return -EINVAL;
}
snd_config_for_each(i, next, cfg) { snd_config_for_each(i, next, cfg) {
const char *id;
n = snd_config_iterator_entry(i); n = snd_config_iterator_entry(i);
snd_config_for_each(j, next2, n) { err = snd_config_get_id(n, &id);
const char *id; if (err < 0)
n2 = snd_config_iterator_entry(i); continue;
err = snd_config_get_id(n2, &id);
if (err < 0)
continue;
/* alloc new value */ /* alloc new value */
curr = calloc(1, sizeof(struct ucm_value)); curr = calloc(1, sizeof(struct ucm_value));
if (curr == NULL) if (curr == NULL)
return -ENOMEM;
list_add_tail(&curr->list, base);
curr->name = strdup(id);
if (curr->name == NULL)
return -ENOMEM;
type = snd_config_get_type(n);
switch (type) {
case SND_CONFIG_TYPE_INTEGER:
curr->data = malloc(16);
if (curr->data == NULL)
return -ENOMEM; return -ENOMEM;
list_add_tail(&curr->list, base); snd_config_get_integer(n, &l);
curr->name = strdup(id); sprintf(curr->data, "%li", l);
if (curr->name == NULL) break;
case SND_CONFIG_TYPE_INTEGER64:
curr->data = malloc(32);
if (curr->data == NULL)
return -ENOMEM; return -ENOMEM;
type = snd_config_get_type(n2); snd_config_get_integer64(n, &ll);
switch (type) { sprintf(curr->data, "%lli", ll);
case SND_CONFIG_TYPE_INTEGER: break;
curr->data = malloc(16); case SND_CONFIG_TYPE_REAL:
if (curr->data == NULL) curr->data = malloc(64);
return -ENOMEM; if (curr->data == NULL)
snd_config_get_integer(n2, &l); return -ENOMEM;
sprintf(curr->data, "%li", l); snd_config_get_real(n, &d);
break; sprintf(curr->data, "%-16g", d);
case SND_CONFIG_TYPE_INTEGER64: break;
curr->data = malloc(32); case SND_CONFIG_TYPE_STRING:
if (curr->data == NULL) err = parse_string(n, &curr->data);
return -ENOMEM; if (err < 0) {
snd_config_get_integer64(n2, &ll); uc_error("error: unable to parse a string for id '%s'!", id);
sprintf(curr->data, "%lli", ll); return err;
break;
case SND_CONFIG_TYPE_REAL:
curr->data = malloc(64);
if (curr->data == NULL)
return -ENOMEM;
snd_config_get_real(n2, &d);
sprintf(curr->data, "%-16g", d);
break;
case SND_CONFIG_TYPE_STRING:
err = parse_string(n2, &curr->data);
if (err < 0) {
uc_error("error: unable to parse a string for id '%s'!", id);
return err;
}
break;
default:
uc_error("error: invalid type %i in Value compound", type);
return -EINVAL;
} }
break;
default:
uc_error("error: invalid type %i in Value compound", type);
return -EINVAL;
} }
} }
@ -322,6 +363,10 @@ static int parse_value(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
* ... * ...
* ] * ]
* *
* TransitionSequence."ToModifierName" [
* ...
* ]
*
* # Optional TQ and ALSA PCMs * # Optional TQ and ALSA PCMs
* Value { * Value {
* TQ Voice * TQ Voice
@ -377,18 +422,12 @@ static int parse_modifier(snd_use_case_mgr_t *uc_mgr,
} }
if (strcmp(id, "SupportedDevice") == 0) { if (strcmp(id, "SupportedDevice") == 0) {
struct dev_list *sdev; err = parse_supported_device(uc_mgr, &modifier->dev_list, n);
sdev = calloc(1, sizeof(struct dev_list));
if (sdev == NULL)
return -ENOMEM;
err = parse_string(n, &sdev->name);
if (err < 0) { if (err < 0) {
free(sdev); uc_error("error: failed to parse supported"
" device list");
return err; return err;
} }
list_add(&sdev->list, &modifier->dev_list);
continue;
} }
if (strcmp(id, "EnableSequence") == 0) { if (strcmp(id, "EnableSequence") == 0) {
@ -411,7 +450,7 @@ static int parse_modifier(snd_use_case_mgr_t *uc_mgr,
continue; continue;
} }
if (strcmp(id, "TransitionModifier") == 0) { if (strcmp(id, "TransitionSequence") == 0) {
err = parse_transition(uc_mgr, &modifier->transition_list, n); err = parse_transition(uc_mgr, &modifier->transition_list, n);
if (err < 0) { if (err < 0) {
uc_error("error: failed to parse transition" uc_error("error: failed to parse transition"
@ -454,6 +493,10 @@ static int parse_modifier(snd_use_case_mgr_t *uc_mgr,
* ... * ...
* ] * ]
* *
* TransitionSequence."ToDevice" [
* ...
* ]
*
* Value { * Value {
* PlaybackVolume "name='Master Playback Volume',index=2" * PlaybackVolume "name='Master Playback Volume',index=2"
* PlaybackSwitch "name='Master Playback Switch',index=2" * PlaybackSwitch "name='Master Playback Switch',index=2"
@ -527,8 +570,8 @@ static int parse_device_index(snd_use_case_mgr_t *uc_mgr,
continue; continue;
} }
if (strcmp(id, "TransitionDevice") == 0) { if (strcmp(id, "TransitionSequence") == 0) {
uc_dbg("TransitionDevice"); uc_dbg("TransitionSequence");
err = parse_transition(uc_mgr, &device->transition_list, n); err = parse_transition(uc_mgr, &device->transition_list, n);
if (err < 0) { if (err < 0) {
uc_error("error: failed to parse transition" uc_error("error: failed to parse transition"
@ -596,11 +639,16 @@ static int parse_device(snd_use_case_mgr_t *uc_mgr,
* cset "name='Master Playback Volume',index=2 50,50" * cset "name='Master Playback Volume',index=2 50,50"
* ] * ]
* *
* # Optional transition verb
* TransitionSequence."ToCaseName" [
* msleep 1
* ]
*
* # Optional TQ and ALSA PCMs * # Optional TQ and ALSA PCMs
* Value { * Value {
* TQ HiFi * TQ HiFi
* CapturePCM 0 * CapturePCM "hw:0"
* PlaybackPCM 0 * PlaybackPCM "hw:0"
* } * }
* } * }
*/ */
@ -621,7 +669,7 @@ static int parse_verb(snd_use_case_mgr_t *uc_mgr,
if (strcmp(id, "EnableSequence") == 0) { if (strcmp(id, "EnableSequence") == 0) {
uc_dbg("Parse EnableSequence"); uc_dbg("Parse EnableSequence");
err = parse_sequence(uc_mgr, &verb->enable_list, cfg); err = parse_sequence(uc_mgr, &verb->enable_list, n);
if (err < 0) { if (err < 0) {
uc_error("error: failed to parse verb enable sequence"); uc_error("error: failed to parse verb enable sequence");
return err; return err;
@ -631,7 +679,7 @@ static int parse_verb(snd_use_case_mgr_t *uc_mgr,
if (strcmp(id, "DisableSequence") == 0) { if (strcmp(id, "DisableSequence") == 0) {
uc_dbg("Parse DisableSequence"); uc_dbg("Parse DisableSequence");
err = parse_sequence(uc_mgr, &verb->disable_list, cfg); err = parse_sequence(uc_mgr, &verb->disable_list, n);
if (err < 0) { if (err < 0) {
uc_error("error: failed to parse verb disable sequence"); uc_error("error: failed to parse verb disable sequence");
return err; return err;
@ -639,11 +687,11 @@ static int parse_verb(snd_use_case_mgr_t *uc_mgr,
continue; continue;
} }
if (strcmp(id, "TransitionVerb") == 0) { if (strcmp(id, "TransitionSequence") == 0) {
uc_dbg("Parse TransitionVerb"); uc_dbg("Parse TransitionSequence");
err = parse_transition(uc_mgr, &verb->transition_list, n); err = parse_transition(uc_mgr, &verb->transition_list, n);
if (err < 0) { if (err < 0) {
uc_error("error: failed to parse transition verb"); uc_error("error: failed to parse transition sequence");
return err; return err;
} }
continue; continue;
@ -682,6 +730,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
struct use_case_verb *verb; struct use_case_verb *verb;
snd_config_t *cfg; snd_config_t *cfg;
char filename[MAX_FILE]; char filename[MAX_FILE];
char *env = getenv(ALSA_CONFIG_UCM_VAR);
int err; int err;
/* allocate verb */ /* allocate verb */
@ -703,7 +752,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
return -ENOMEM; return -ENOMEM;
/* open Verb file for reading */ /* open Verb file for reading */
snprintf(filename, sizeof(filename), "%s/%s/%s", ALSA_USE_CASE_DIR, snprintf(filename, sizeof(filename), "%s/%s/%s",
env ? env : ALSA_USE_CASE_DIR,
uc_mgr->card_name, file); uc_mgr->card_name, file);
filename[sizeof(filename)-1] = '\0'; filename[sizeof(filename)-1] = '\0';
@ -832,16 +882,18 @@ static int parse_master_section(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
*/ */
static int parse_controls(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) static int parse_controls(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
{ {
struct list_head list;
int err; int err;
INIT_LIST_HEAD(&list); if (!list_empty(&uc_mgr->default_list)) {
err = parse_sequence(uc_mgr, &list, cfg); uc_error("Default list is not empty");
return -EINVAL;
}
err = parse_sequence(uc_mgr, &uc_mgr->default_list, cfg);
if (err < 0) { if (err < 0) {
uc_error("Unable to parse SectionDefaults"); uc_error("Unable to parse SectionDefaults");
return err; return err;
} }
printf("parse_controls - not yet implemented\n");
return 0; return 0;
} }
@ -931,9 +983,6 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
return 0; return 0;
} }
/** 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) static int load_master_config(const char *card_name, snd_config_t **cfg)
{ {
char filename[MAX_FILE]; char filename[MAX_FILE];
@ -992,18 +1041,19 @@ static int filename_filter(const struct dirent *dirent)
/* scan all cards and comments */ /* scan all cards and comments */
int uc_mgr_scan_master_configs(const char **_list[]) int uc_mgr_scan_master_configs(const char **_list[])
{ {
char filename[MAX_FILE]; char filename[MAX_FILE], dfl[MAX_FILE];
char *env = getenv(ALSA_CONFIG_UCM_VAR); char *env = getenv(ALSA_CONFIG_UCM_VAR);
const char **list; const char **list;
snd_config_t *cfg, *c; snd_config_t *cfg, *c;
int i, cnt, err; int i, cnt, err;
ssize_t ss;
struct dirent **namelist; struct dirent **namelist;
snprintf(filename, sizeof(filename)-1, snprintf(filename, sizeof(filename)-1,
"%s", env ? env : ALSA_USE_CASE_DIR); "%s", env ? env : ALSA_USE_CASE_DIR);
filename[MAX_FILE-1] = '\0'; filename[MAX_FILE-1] = '\0';
err = scandir(filename, &namelist, filename_filter, alphasort); err = scandir(filename, &namelist, filename_filter, versionsort);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
uc_error("error: could not scan directory %s: %s", uc_error("error: could not scan directory %s: %s",
@ -1012,6 +1062,20 @@ int uc_mgr_scan_master_configs(const char **_list[])
} }
cnt = err; cnt = err;
dfl[0] = '\0';
if (strlen(filename) + 8 < sizeof(filename)) {
strcat(filename, "/default");
ss = readlink(filename, dfl, sizeof(dfl)-1);
if (ss >= 0) {
dfl[ss] = '\0';
dfl[sizeof(dfl)-1] = '\0';
if (dfl[0] && dfl[strlen(dfl)-1] == '/')
dfl[strlen(dfl)-1] = '\0';
} else {
dfl[0] = '\0';
}
}
list = calloc(1, cnt * 2 * sizeof(char *)); list = calloc(1, cnt * 2 * sizeof(char *));
if (list == NULL) { if (list == NULL) {
err = -ENOMEM; err = -ENOMEM;
@ -1036,6 +1100,14 @@ int uc_mgr_scan_master_configs(const char **_list[])
err = -ENOMEM; err = -ENOMEM;
goto __err; goto __err;
} }
if (strcmp(dfl, list[i * 2]) == 0) {
/* default to top */
const char *save1 = list[i * 2];
const char *save2 = list[i * 2 + 1];
memmove(list + 2, list, i * 2 * sizeof(char *));
list[0] = save1;
list[1] = save2;
}
} }
err = cnt * 2; err = cnt * 2;

View file

@ -196,5 +196,6 @@ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr);
int uc_mgr_scan_master_configs(const char **_list[]); int uc_mgr_scan_master_configs(const char **_list[]);
void uc_mgr_free_sequence_element(struct sequence_element *seq); void uc_mgr_free_sequence_element(struct sequence_element *seq);
void uc_mgr_free_transition_element(struct transition_sequence *seq);
void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr); void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr);
void uc_mgr_free(snd_use_case_mgr_t *uc_mgr); void uc_mgr_free(snd_use_case_mgr_t *uc_mgr);

View file

@ -94,7 +94,8 @@ void uc_mgr_free_value(struct list_head *base)
val = list_entry(pos, struct ucm_value, list); val = list_entry(pos, struct ucm_value, list);
free(val->name); free(val->name);
free(val->data); free(val->data);
list_del(pos); list_del(&val->list);
free(val);
} }
} }
@ -106,8 +107,8 @@ void uc_mgr_free_dev_list(struct list_head *base)
list_for_each_safe(pos, npos, base) { list_for_each_safe(pos, npos, base) {
dlist = list_entry(pos, struct dev_list, list); dlist = list_entry(pos, struct dev_list, list);
free(dlist->name); free(dlist->name);
list_del(&dlist->list);
free(dlist); free(dlist);
list_del(pos);
} }
} }
@ -133,11 +134,18 @@ void uc_mgr_free_sequence(struct list_head *base)
list_for_each_safe(pos, npos, base) { list_for_each_safe(pos, npos, base) {
seq = list_entry(pos, struct sequence_element, list); seq = list_entry(pos, struct sequence_element, list);
list_del(&seq->list);
uc_mgr_free_sequence_element(seq); uc_mgr_free_sequence_element(seq);
list_del(pos);
} }
} }
void uc_mgr_free_transition_element(struct transition_sequence *tseq)
{
free(tseq->name);
uc_mgr_free_sequence(&tseq->transition_list);
free(tseq);
}
void uc_mgr_free_transition(struct list_head *base) void uc_mgr_free_transition(struct list_head *base)
{ {
struct list_head *pos, *npos; struct list_head *pos, *npos;
@ -145,10 +153,8 @@ void uc_mgr_free_transition(struct list_head *base)
list_for_each_safe(pos, npos, base) { list_for_each_safe(pos, npos, base) {
tseq = list_entry(pos, struct transition_sequence, list); tseq = list_entry(pos, struct transition_sequence, list);
free(tseq->name); list_del(&tseq->list);
uc_mgr_free_sequence(&tseq->transition_list); uc_mgr_free_transition_element(tseq);
free(tseq);
list_del(pos);
} }
} }
@ -166,8 +172,8 @@ void uc_mgr_free_modifier(struct list_head *base)
uc_mgr_free_transition(&mod->transition_list); uc_mgr_free_transition(&mod->transition_list);
uc_mgr_free_dev_list(&mod->dev_list); uc_mgr_free_dev_list(&mod->dev_list);
uc_mgr_free_value(&mod->value_list); uc_mgr_free_value(&mod->value_list);
list_del(&mod->list);
free(mod); free(mod);
list_del(pos);
} }
} }
@ -184,8 +190,8 @@ void uc_mgr_free_device(struct list_head *base)
uc_mgr_free_sequence(&dev->disable_list); uc_mgr_free_sequence(&dev->disable_list);
uc_mgr_free_transition(&dev->transition_list); uc_mgr_free_transition(&dev->transition_list);
uc_mgr_free_value(&dev->value_list); uc_mgr_free_value(&dev->value_list);
list_del(&dev->list);
free(dev); free(dev);
list_del(pos);
} }
} }
@ -204,8 +210,8 @@ void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr)
uc_mgr_free_value(&verb->value_list); uc_mgr_free_value(&verb->value_list);
uc_mgr_free_device(&verb->device_list); uc_mgr_free_device(&verb->device_list);
uc_mgr_free_modifier(&verb->modifier_list); uc_mgr_free_modifier(&verb->modifier_list);
list_del(&verb->list);
free(verb); free(verb);
list_del(pos);
} }
uc_mgr_free_sequence(&uc_mgr->default_list); uc_mgr_free_sequence(&uc_mgr->default_list);
free(uc_mgr->comment); free(uc_mgr->comment);

View file

@ -0,0 +1,24 @@
SectionVerb {
EnableSequence [
exec "Case1 enable seq"
]
DisableSequence [
exec "Case2 disable seq"
]
TransitionVerb."Case2" [
exec "Case1->Case2 transition seq"
]
Value {
TestValue1 "123"
}
}
SectionDevice."Device1".0 {
}
SectionModifier."Modifier1" {
SupportedDevice [
"Device1"
]
}

View file

@ -0,0 +1,11 @@
Comment "A test HDA card"
SectionUseCase."Case1" {
File "Case1.conf"
Comment "Case1 Comment"
}
SectionDefaults [
exec "my prg"
msleep 1
]