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
228
src/ucm/main.c
228
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);
|
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
|
* \brief Find modifier
|
||||||
* \param verb Use case verb
|
* \param verb Use case verb
|
||||||
|
|
@ -488,20 +503,16 @@ int snd_use_case_mgr_close(snd_use_case_mgr_t *uc_mgr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* \brief Reset sound card controls to default values.
|
* Tear down current use case verb, device and modifier.
|
||||||
* \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)
|
static int dismantle_use_case(snd_use_case_mgr_t *uc_mgr)
|
||||||
{
|
{
|
||||||
struct list_head *pos, *npos;
|
struct list_head *pos, *npos;
|
||||||
struct use_case_modifier *modifier;
|
struct use_case_modifier *modifier;
|
||||||
struct use_case_device *device;
|
struct use_case_device *device;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
pthread_mutex_lock(&uc_mgr->mutex);
|
|
||||||
|
|
||||||
list_for_each_safe(pos, npos, &uc_mgr->active_modifiers) {
|
list_for_each_safe(pos, npos, &uc_mgr->active_modifiers) {
|
||||||
modifier = list_entry(pos, struct use_case_modifier,
|
modifier = list_entry(pos, struct use_case_modifier,
|
||||||
active_list);
|
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);
|
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);
|
pthread_mutex_unlock(&uc_mgr->mutex);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -950,6 +978,190 @@ long snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
|
||||||
return err;
|
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
|
* \brief Set new
|
||||||
* \param uc_mgr Use case manager
|
* \param uc_mgr Use case manager
|
||||||
|
|
@ -961,7 +1173,7 @@ int snd_use_case_set(snd_use_case_mgr_t *uc_mgr,
|
||||||
const char *identifier,
|
const char *identifier,
|
||||||
const char *value)
|
const char *value)
|
||||||
{
|
{
|
||||||
char *str, *str1;
|
char *str, *str1;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
pthread_mutex_lock(&uc_mgr->mutex);
|
pthread_mutex_lock(&uc_mgr->mutex);
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,8 @@
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
#include "use-case.h"
|
#include "use-case.h"
|
||||||
|
|
||||||
#define PRE_SEQ 0
|
|
||||||
#define POST_SEQ 1
|
|
||||||
#define MAX_FILE 256
|
#define MAX_FILE 256
|
||||||
#define ALSA_USE_CASE_DIR ALSA_CONFIG_DIR "/ucm"
|
#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_CSET 1
|
||||||
#define SEQUENCE_ELEMENT_TYPE_SLEEP 2
|
#define SEQUENCE_ELEMENT_TYPE_SLEEP 2
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue