mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
ucm: added implementation for other ucm parts, only card name list is missing
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
404cd090b2
commit
6c6dc230bc
2 changed files with 220 additions and 12 deletions
226
src/ucm/main.c
226
src/ucm/main.c
|
|
@ -313,6 +313,21 @@ static inline struct use_case_verb *find_verb(snd_use_case_mgr_t *uc_mgr,
|
|||
verb_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Find device
|
||||
* \param verb Use case verb
|
||||
* \param device_name device to find
|
||||
* \return structure on success, otherwise a NULL (not found)
|
||||
*/
|
||||
static inline struct use_case_device *
|
||||
find_device(struct use_case_verb *verb,
|
||||
const char *device_name)
|
||||
{
|
||||
return find(&verb->device_list,
|
||||
struct use_case_device, list, name,
|
||||
device_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Find modifier
|
||||
* \param verb Use case verb
|
||||
|
|
@ -488,20 +503,16 @@ int snd_use_case_mgr_close(snd_use_case_mgr_t *uc_mgr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reset sound card controls to default values.
|
||||
* \param uc_mgr Use case manager
|
||||
* \return zero on success, otherwise a negative error code
|
||||
/*
|
||||
* Tear down current use case verb, device and modifier.
|
||||
*/
|
||||
int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
|
||||
static int dismantle_use_case(snd_use_case_mgr_t *uc_mgr)
|
||||
{
|
||||
struct list_head *pos, *npos;
|
||||
struct use_case_modifier *modifier;
|
||||
struct use_case_device *device;
|
||||
int err;
|
||||
|
||||
pthread_mutex_lock(&uc_mgr->mutex);
|
||||
|
||||
list_for_each_safe(pos, npos, &uc_mgr->active_modifiers) {
|
||||
modifier = list_entry(pos, struct use_case_modifier,
|
||||
active_list);
|
||||
|
|
@ -529,6 +540,23 @@ int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
|
|||
|
||||
err = execute_sequence(uc_mgr, &uc_mgr->default_list);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reset sound card controls to default values.
|
||||
* \param uc_mgr Use case manager
|
||||
* \return zero on success, otherwise a negative error code
|
||||
*/
|
||||
int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
|
||||
{
|
||||
int err;
|
||||
|
||||
pthread_mutex_lock(&uc_mgr->mutex);
|
||||
err = execute_sequence(uc_mgr, &uc_mgr->default_list);
|
||||
INIT_LIST_HEAD(&uc_mgr->active_modifiers);
|
||||
INIT_LIST_HEAD(&uc_mgr->active_devices);
|
||||
uc_mgr->active_verb = NULL;
|
||||
pthread_mutex_unlock(&uc_mgr->mutex);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -950,6 +978,190 @@ long snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int handle_transition_verb(snd_use_case_mgr_t *uc_mgr,
|
||||
struct use_case_verb *new_verb)
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct transition_sequence *trans;
|
||||
int err;
|
||||
|
||||
list_for_each(pos, &uc_mgr->active_verb->transition_list) {
|
||||
trans = list_entry(pos, struct transition_sequence, list);
|
||||
if (strcmp(trans->name, new_verb->name) == 0) {
|
||||
err = execute_sequence(uc_mgr, &trans->transition_list);
|
||||
if (err >= 0)
|
||||
return 1;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_verb_user(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *verb_name)
|
||||
{
|
||||
struct use_case_verb *verb;
|
||||
int err;
|
||||
|
||||
if (uc_mgr->active_verb &&
|
||||
strcmp(uc_mgr->active_verb->name, verb_name) == 0)
|
||||
return 0;
|
||||
if (strcmp(verb_name, SND_USE_CASE_VERB_INACTIVE) != 0) {
|
||||
verb = find_verb(uc_mgr, verb_name);
|
||||
if (verb == NULL)
|
||||
return -ENOENT;
|
||||
} else {
|
||||
verb = NULL;
|
||||
}
|
||||
if (uc_mgr->active_verb) {
|
||||
err = handle_transition_verb(uc_mgr, verb);
|
||||
if (err == 0) {
|
||||
err = dismantle_use_case(uc_mgr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else if (err == 1) {
|
||||
uc_mgr->active_verb = verb;
|
||||
verb = NULL;
|
||||
} else {
|
||||
verb = NULL; /* show error */
|
||||
}
|
||||
}
|
||||
if (verb) {
|
||||
err = set_verb(uc_mgr, verb, 1);
|
||||
if (err < 0)
|
||||
uc_error("error: failed to initialize new use case: %s",
|
||||
verb_name);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int set_device_user(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *device_name,
|
||||
int enable)
|
||||
{
|
||||
struct use_case_device *device;
|
||||
|
||||
if (uc_mgr->active_verb == NULL)
|
||||
return -ENOENT;
|
||||
device = find_device(uc_mgr->active_verb, device_name);
|
||||
if (device == NULL)
|
||||
return -ENOENT;
|
||||
return set_device(uc_mgr, device, enable);
|
||||
}
|
||||
|
||||
static int set_modifier_user(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *modifier_name,
|
||||
int enable)
|
||||
{
|
||||
struct use_case_modifier *modifier;
|
||||
|
||||
if (uc_mgr->active_verb == NULL)
|
||||
return -ENOENT;
|
||||
modifier = find_modifier(uc_mgr->active_verb, modifier_name);
|
||||
if (modifier == NULL)
|
||||
return -ENOENT;
|
||||
return set_modifier(uc_mgr, modifier, enable);
|
||||
}
|
||||
|
||||
static int switch_device(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *old_device,
|
||||
const char *new_device)
|
||||
{
|
||||
struct use_case_device *xold, *xnew;
|
||||
struct transition_sequence *trans;
|
||||
struct list_head *pos;
|
||||
int err, seq_found = 0;
|
||||
|
||||
if (uc_mgr->active_verb == NULL)
|
||||
return -ENOENT;
|
||||
if (device_status(uc_mgr, old_device) == 0) {
|
||||
uc_error("error: device %s not enabled", old_device);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (device_status(uc_mgr, new_device) != 0) {
|
||||
uc_error("error: device %s already enabled", new_device);
|
||||
return -EINVAL;
|
||||
}
|
||||
xold = find_device(uc_mgr->active_verb, old_device);
|
||||
if (xold == NULL)
|
||||
return -ENOENT;
|
||||
xnew = find_device(uc_mgr->active_verb, new_device);
|
||||
if (xold == NULL)
|
||||
return -ENOENT;
|
||||
err = 0;
|
||||
list_for_each(pos, &xold->transition_list) {
|
||||
trans = list_entry(pos, struct transition_sequence, list);
|
||||
if (strcmp(trans->name, new_device) == 0) {
|
||||
err = execute_sequence(uc_mgr, &trans->transition_list);
|
||||
if (err >= 0) {
|
||||
list_del(&xold->active_list);
|
||||
list_add_tail(&xnew->active_list, &uc_mgr->active_devices);
|
||||
}
|
||||
seq_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!seq_found) {
|
||||
err = set_device(uc_mgr, xold, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = set_device(uc_mgr, xnew, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int switch_modifier(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *old_modifier,
|
||||
const char *new_modifier)
|
||||
{
|
||||
struct use_case_modifier *xold, *xnew;
|
||||
struct transition_sequence *trans;
|
||||
struct list_head *pos;
|
||||
int err, seq_found = 0;
|
||||
|
||||
if (uc_mgr->active_verb == NULL)
|
||||
return -ENOENT;
|
||||
if (modifier_status(uc_mgr, old_modifier) == 0) {
|
||||
uc_error("error: modifier %s not enabled", old_modifier);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (modifier_status(uc_mgr, new_modifier) != 0) {
|
||||
uc_error("error: modifier %s already enabled", new_modifier);
|
||||
return -EINVAL;
|
||||
}
|
||||
xold = find_modifier(uc_mgr->active_verb, old_modifier);
|
||||
if (xold == NULL)
|
||||
return -ENOENT;
|
||||
xnew = find_modifier(uc_mgr->active_verb, new_modifier);
|
||||
if (xold == NULL)
|
||||
return -ENOENT;
|
||||
err = 0;
|
||||
list_for_each(pos, &xold->transition_list) {
|
||||
trans = list_entry(pos, struct transition_sequence, list);
|
||||
if (strcmp(trans->name, new_modifier) == 0) {
|
||||
err = execute_sequence(uc_mgr, &trans->transition_list);
|
||||
if (err >= 0) {
|
||||
list_del(&xold->active_list);
|
||||
list_add_tail(&xnew->active_list, &uc_mgr->active_modifiers);
|
||||
}
|
||||
seq_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!seq_found) {
|
||||
err = set_modifier(uc_mgr, xold, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = set_modifier(uc_mgr, xnew, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set new
|
||||
* \param uc_mgr Use case manager
|
||||
|
|
|
|||
|
|
@ -39,12 +39,8 @@
|
|||
#include "local.h"
|
||||
#include "use-case.h"
|
||||
|
||||
#define PRE_SEQ 0
|
||||
#define POST_SEQ 1
|
||||
#define MAX_FILE 256
|
||||
#define ALSA_USE_CASE_DIR ALSA_CONFIG_DIR "/ucm"
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
#define VERB_NOT_INITIALISED -1
|
||||
|
||||
#define SEQUENCE_ELEMENT_TYPE_CSET 1
|
||||
#define SEQUENCE_ELEMENT_TYPE_SLEEP 2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue