More changes to the ordinary mixer API

This commit is contained in:
Jaroslav Kysela 2003-10-13 12:06:45 +00:00
parent 72c814db2a
commit ab61b62cb4
9 changed files with 576 additions and 234 deletions

View file

@ -455,6 +455,7 @@ int snd_hctl_close(snd_hctl_t *hctl);
int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock);
int snd_hctl_poll_descriptors_count(snd_hctl_t *hctl);
int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int space);
int snd_hctl_poll_descriptors_revents(snd_hctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
unsigned int snd_hctl_get_count(snd_hctl_t *hctl);
int snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t hsort);
snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl);

View file

@ -29,6 +29,25 @@
#include <alsa/asoundlib.h>
/*
* Abbreviations:
*
* FLVOL - Front Left Volume (0-1000)
* FCLVOL - Front Center Left Volume (0-1000)
* FCVOL - Front Center Volume (0-1000)
* FCRVOL - Front Center Right Volume (0-1000)
* FRVOL - Front Right Volume (0-1000)
* FSLVOL - Front Side Left Volume (0-1000)
* FSRVOL - Front Side Right Volume (0-1000)
* RSLVOL - Rear Side Left Volume (0-1000)
* RSRVOL - Rear Side Right Volume (0-1000)
* RLVOL - Rear Left Volume (0-1000)
* RCVOL - Rear Center Volume (0-1000)
* RRVOL - Rear Right Volume (0-1000)
* LFEVOL - Low Frequency Effects (Subwoofer) Volume (0-1000)
* OVRVOL - Overhead Volume (0-1000)
*/
/** Ordinary Mixer I/O type */
enum sndo_mixer_io_type {
@ -36,158 +55,131 @@ enum sndo_mixer_io_type {
* playback section
*/
/** Master volume - left (0-1000) */
SNDO_MIO_MASTER_LVOL = 0,
/** Master volume - right (0-1000) */
SNDO_MIO_MASTER_RVOL,
/** Master volume - left surround (0-1000) */
SNDO_MIO_MASTER_LSVOL = 0,
/** Master volume - right surround (0-1000) */
SNDO_MIO_MASTER_RSVOL,
/** Master volume - center (0-1000) */
SNDO_MIO_MASTER_CVOL = 0,
/** Master volume - LFE (0-1000) */
/* Master */
SNDO_MIO_MASTER_FLVOL = 0 * 0x40,
SNDO_MIO_MASTER_FCLVOL,
SNDO_MIO_MASTER_FCVOL,
SNDO_MIO_MASTER_FCRVOL,
SNDO_MIO_MASTER_FRVOL,
SNDO_MIO_MASTER_FSLVOL,
SNDO_MIO_MASTER_FSRVOL,
SNDO_MIO_MASTER_RSLVOL,
SNDO_MIO_MASTER_RSRVOL,
SNDO_MIO_MASTER_RLVOL,
SNDO_MIO_MASTER_RCVOL,
SNDO_MIO_MASTER_RRVOL,
SNDO_MIO_MASTER_LFEVOL,
/** Master volume - left mute (0 = off, 1 = on) */
SNDO_MIO_MASTER_LMUTE,
/** Master volume - right mute (0 = off, 1 = on) */
SNDO_MIO_MASTER_RMUTE,
/** Master volume - left surround mute (0 = off, 1 = on) */
SNDO_MIO_MASTER_LSMUTE,
/** Master volume - right surround mute (0 = off, 1 = on) */
SNDO_MIO_MASTER_RSMUTE,
/** Master volume - center mute (0 = off, 1 = on) */
SNDO_MIO_MASTER_CMUTE,
/** Master volume - LFE mute (0 = off, 1 = on) */
SNDO_MIO_MASTER_LFEMUTE,
SNDO_MIO_MASTER_OVRVOL,
/** PCM volume - left (0-1000) */
SNDO_MIO_PCM_LVOL = 0,
/** PCM volume - right (0-1000) */
SNDO_MIO_PCM_RVOL,
/** PCM volume - left surround (0-1000) */
SNDO_MIO_PCM_LSVOL = 0,
/** PCM volume - right surround (0-1000) */
SNDO_MIO_PCM_RSVOL,
/** PCM volume - center (0-1000) */
SNDO_MIO_PCM_CVOL = 0,
/** PCM volume - LFE (0-1000) */
/* PCM */
SNDO_MIO_PCM_FLVOL = 1 * 0x40,
SNDO_MIO_PCM_FCLVOL,
SNDO_MIO_PCM_FCVOL,
SNDO_MIO_PCM_FCRVOL,
SNDO_MIO_PCM_FRVOL,
SNDO_MIO_PCM_FSLVOL,
SNDO_MIO_PCM_FSRVOL,
SNDO_MIO_PCM_RSLVOL,
SNDO_MIO_PCM_RSRVOL,
SNDO_MIO_PCM_RLVOL,
SNDO_MIO_PCM_RCVOL,
SNDO_MIO_PCM_RRVOL,
SNDO_MIO_PCM_LFEVOL,
/** PCM volume - left mute (0 = off, 1 = on) */
SNDO_MIO_PCM_LMUTE,
/** PCM volume - right mute (0 = off, 1 = on) */
SNDO_MIO_PCM_RMUTE,
/** PCM volume - left surround mute (0 = off, 1 = on) */
SNDO_MIO_PCM_LSMUTE,
/** PCM volume - right surround mute (0 = off, 1 = on) */
SNDO_MIO_PCM_RSMUTE,
/** PCM volume - center mute (0 = off, 1 = on) */
SNDO_MIO_PCM_CMUTE,
/** PCM volume - LFE mute (0 = off, 1 = on) */
SNDO_MIO_PCM_LFEMUTE,
SNDO_MIO_PCM_OVRVOL,
/** LINE volume - left (0-1000) */
SNDO_MIO_LINE_LVOL = 0,
/** LINE volume - right (0-1000) */
SNDO_MIO_LINE_RVOL,
/** LINE volume - left surround (0-1000) */
SNDO_MIO_LINE_LSVOL = 0,
/** LINE volume - right surround (0-1000) */
SNDO_MIO_LINE_RSVOL,
/** LINE volume - center (0-1000) */
SNDO_MIO_LINE_CVOL = 0,
/** LINE volume - LFE (0-1000) */
/* LINE */
SNDO_MIO_LINE_FLVOL = 2 * 0x40,
SNDO_MIO_LINE_FCLVOL,
SNDO_MIO_LINE_FCVOL,
SNDO_MIO_LINE_FCRVOL,
SNDO_MIO_LINE_FRVOL,
SNDO_MIO_LINE_FSLVOL,
SNDO_MIO_LINE_FSRVOL,
SNDO_MIO_LINE_RSLVOL,
SNDO_MIO_LINE_RSRVOL,
SNDO_MIO_LINE_RLVOL,
SNDO_MIO_LINE_RCVOL,
SNDO_MIO_LINE_RRVOL,
SNDO_MIO_LINE_LFEVOL,
/** LINE volume - left mute (0 = off, 1 = on) */
SNDO_MIO_LINE_LMUTE,
/** LINE volume - right mute (0 = off, 1 = on) */
SNDO_MIO_LINE_RMUTE,
/** LINE volume - left surround mute (0 = off, 1 = on) */
SNDO_MIO_LINE_LSMUTE,
/** LINE volume - right surround mute (0 = off, 1 = on) */
SNDO_MIO_LINE_RSMUTE,
/** LINE volume - center mute (0 = off, 1 = on) */
SNDO_MIO_LINE_CMUTE,
/** LINE volume - LFE mute (0 = off, 1 = on) */
SNDO_MIO_LINE_LFEMUTE,
SNDO_MIO_LINE_OVRVOL,
/** MIC volume - left (0-1000) */
SNDO_MIO_MIC_LVOL = 0,
/** MIC volume - right (0-1000) */
SNDO_MIO_MIC_RVOL,
/** MIC volume - left surround (0-1000) */
SNDO_MIO_MIC_LSVOL = 0,
/** MIC volume - right surround (0-1000) */
SNDO_MIO_MIC_RSVOL,
/** MIC volume - center (0-1000) */
SNDO_MIO_MIC_CVOL = 0,
/** MIC volume - LFE (0-1000) */
/* MIC */
SNDO_MIO_MIC_FLVOL = 3 * 0x40,
SNDO_MIO_MIC_FCLVOL,
SNDO_MIO_MIC_FCVOL,
SNDO_MIO_MIC_FCRVOL,
SNDO_MIO_MIC_FRVOL,
SNDO_MIO_MIC_FSLVOL,
SNDO_MIO_MIC_FSRVOL,
SNDO_MIO_MIC_RSLVOL,
SNDO_MIO_MIC_RSRVOL,
SNDO_MIO_MIC_RLVOL,
SNDO_MIO_MIC_RCVOL,
SNDO_MIO_MIC_RRVOL,
SNDO_MIO_MIC_LFEVOL,
/** MIC volume - left mute (0 = off, 1 = on) */
SNDO_MIO_MIC_LMUTE,
/** MIC volume - right mute (0 = off, 1 = on) */
SNDO_MIO_MIC_RMUTE,
/** MIC volume - left surround mute (0 = off, 1 = on) */
SNDO_MIO_MIC_LSMUTE,
/** MIC volume - right surround mute (0 = off, 1 = on) */
SNDO_MIO_MIC_RSMUTE,
/** MIC volume - center mute (0 = off, 1 = on) */
SNDO_MIO_MIC_CMUTE,
/** MIC volume - LFE mute (0 = off, 1 = on) */
SNDO_MIO_MIC_LFEMUTE,
SNDO_MIO_MIC_OVRVOL,
/** CD volume - left (0-1000) */
SNDO_MIO_CD_LVOL = 0,
/** CD volume - right (0-1000) */
SNDO_MIO_CD_RVOL,
/** CD volume - left surround (0-1000) */
SNDO_MIO_CD_LSVOL = 0,
/** CD volume - right surround (0-1000) */
SNDO_MIO_CD_RSVOL,
/** CD volume - center (0-1000) */
SNDO_MIO_CD_CVOL = 0,
/** CD volume - LFE (0-1000) */
/* CD */
SNDO_MIO_CD_FLVOL = 4 * 0x40,
SNDO_MIO_CD_FCLVOL,
SNDO_MIO_CD_FCVOL,
SNDO_MIO_CD_FCRVOL,
SNDO_MIO_CD_FRVOL,
SNDO_MIO_CD_FSLVOL,
SNDO_MIO_CD_FSRVOL,
SNDO_MIO_CD_RSLVOL,
SNDO_MIO_CD_RSRVOL,
SNDO_MIO_CD_RLVOL,
SNDO_MIO_CD_RCVOL,
SNDO_MIO_CD_RRVOL,
SNDO_MIO_CD_LFEVOL,
/** CD volume - left mute (0 = off, 1 = on) */
SNDO_MIO_CD_LMUTE,
/** CD volume - right mute (0 = off, 1 = on) */
SNDO_MIO_CD_RMUTE,
/** CD volume - left surround mute (0 = off, 1 = on) */
SNDO_MIO_CD_LSMUTE,
/** CD volume - right surround mute (0 = off, 1 = on) */
SNDO_MIO_CD_RSMUTE,
/** CD volume - center mute (0 = off, 1 = on) */
SNDO_MIO_CD_CMUTE,
/** CD volume - LFE mute (0 = off, 1 = on) */
SNDO_MIO_CD_LFEMUTE,
SNDO_MIO_CD_OVRVOL,
/* AUX */
SNDO_MIO_AUX_FLVOL = 5 * 0x40,
SNDO_MIO_AUX_FCLVOL,
SNDO_MIO_AUX_FCVOL,
SNDO_MIO_AUX_FCRVOL,
SNDO_MIO_AUX_FRVOL,
SNDO_MIO_AUX_FSLVOL,
SNDO_MIO_AUX_FSRVOL,
SNDO_MIO_AUX_RSLVOL,
SNDO_MIO_AUX_RSRVOL,
SNDO_MIO_AUX_RLVOL,
SNDO_MIO_AUX_RCVOL,
SNDO_MIO_AUX_RRVOL,
SNDO_MIO_AUX_LFEVOL,
SNDO_MIO_AUX_OVRVOL,
/*
* capture section
*/
/** capture gain - left (0-1000) */
SNDO_MIO_CGAIN_LVOL = 0x1000,
/** capture gain - right (0-1000) */
SNDO_MIO_CGAIN_RVOL,
/** capture gain - left surround (0-1000) */
SNDO_MIO_CGAIN_LSVOL,
/** capture gain - right surround (0-1000) */
SNDO_MIO_CGAIN_RSVOL,
/** capture gain - center (0-1000) */
SNDO_MIO_CGAIN_CVOL,
/** capture gain - LFE (0-1000) */
SNDO_MIO_CGAIN_LFEVOL,
/* capture gain */
SNDO_MIO_CGAIN_FL = 0x8000,
SNDO_MIO_CGAIN_FCL,
SNDO_MIO_CGAIN_FC,
SNDO_MIO_CGAIN_FCR,
SNDO_MIO_CGAIN_FR,
SNDO_MIO_CGAIN_FSL,
SNDO_MIO_CGAIN_FSR,
SNDO_MIO_CGAIN_RSL,
SNDO_MIO_CGAIN_RSR,
SNDO_MIO_CGAIN_RL,
SNDO_MIO_CGAIN_RC,
SNDO_MIO_CGAIN_RR,
SNDO_MIO_CGAIN_LFE,
SNDO_MIO_CGAIN_OVR,
/** capture source - MIC exclusive switch (0 = off, 1 = on) */
SNDO_MIO_CSOURCE_MIC = 0x1100,
/** capture source - LINE exclusive switch (0 = off, 1 = on) */
/* capture source (0 = off, 1 = on) */
SNDO_MIO_CSOURCE_MIC = 0x8100,
SNDO_MIO_CSOURCE_LINE,
/** capture source - CD exclusive switch (0 = off, 1 = on) */
SNDO_MIO_CSOURCE_CD,
/** capture source - AUX exclusive switch (0 = off, 1 = on) */
SNDO_MIO_CSOURCE_AUX,
/** capture source - MIX exclusive switch (0 = off, 1 = on) */
SNDO_MIO_CSOURCE_MIX
SNDO_MIO_CSOURCE_MIX,
/* misc */
SNDO_MIO_STEREO = 0x8200, /* (0 = off, 1 = on) standard stereo source, might be converted to use all outputs */
};
typedef struct sndo_mixer sndo_mixer_t;
@ -208,8 +200,13 @@ int sndo_mixer_close(sndo_mixer_t *mixer);
int sndo_mixer_poll_descriptors_count(sndo_mixer_t *mixer);
int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space);
int sndo_mixer_poll_descriptors_revents(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
int sndo_mixer_io_get_name(enum sndo_mixer_io_type type, char **name);
int sndo_mixer_io_get(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
int sndo_mixer_io_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int val);
int sndo_mixer_io_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
int sndo_mixer_io_try_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
int sndo_mixer_io_get_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
int sndo_mixer_io_set_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
int sndo_mixer_io_try_set_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val);
int sndo_mixer_io_change(sndo_mixer_t *mixer, enum sndo_mixer_io_type *changed, int changed_array_size);
/** \} */

View file

@ -135,3 +135,9 @@ ALSA_0.9.7 {
sndo_*;
alsa_lisp_*;
} ALSA_0.9.6;
ALSA_0.9.8 {
global:
snd_hctl_poll_descriptors_revents;
} ALSA_0.9.7;

View file

@ -51,6 +51,7 @@ static struct alisp_object * parse_object(struct alisp_instance *instance, int h
static void princ_cons(snd_output_t *out, struct alisp_object * p);
static void princ_object(snd_output_t *out, struct alisp_object * p);
static struct alisp_object * eval(struct alisp_instance *instance, struct alisp_object * p);
static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2);
/* functions */
static struct alisp_object *F_eval(struct alisp_instance *instance, struct alisp_object *);
@ -467,7 +468,7 @@ static int gettoken(struct alisp_instance *instance)
return instance->thistoken;
got_id:
case '_': case '+': case '*': case '/': case '%':
case '!': case '_': case '+': case '*': case '/': case '%':
case '<': case '>': case '=': case '&':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
@ -479,7 +480,7 @@ static int gettoken(struct alisp_instance *instance)
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z':
/* Identifier: [-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */
/* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */
p = instance->token_buffer;
do {
if (p - instance->token_buffer >= instance->token_buffer_max) {
@ -489,7 +490,7 @@ static int gettoken(struct alisp_instance *instance)
}
*p++ = c;
c = xgetc(instance);
} while (isalnum(c) || strchr("_-+*/%<>=&", c) != NULL);
} while (isalnum(c) || strchr("!_-+*/%<>=&", c) != NULL);
xungetc(instance, c);
*p = '\0';
return instance->thistoken = ALISP_IDENTIFIER;
@ -1325,6 +1326,19 @@ static struct alisp_object * F_numeq(struct alisp_instance *instance, struct ali
return &alsa_lisp_nil;
}
/*
* Syntax: (!= expr1 expr2)
*/
static struct alisp_object * F_numneq(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p;
p = F_numeq(instance, args);
if (p == &alsa_lisp_nil)
return &alsa_lisp_t;
return &alsa_lisp_nil;
}
/*
* Syntax: (exfun name)
* Test, if a function exists
@ -1333,7 +1347,7 @@ static struct alisp_object * F_exfun(struct alisp_instance *instance, struct ali
{
struct alisp_object * p1, * p2;
p1 = car(args);
p1 = eval(instance, car(args));
if (p1->type != ALISP_OBJ_STRING && p1->type != ALISP_OBJ_IDENTIFIER)
return &alsa_lisp_nil;
p2 = get_object(instance, p1);
@ -1960,6 +1974,20 @@ struct alisp_object * F_include(struct alisp_instance *instance, struct alisp_ob
return new_integer(instance, res);
}
/*
* Syntax: (call function args...)
*/
struct alisp_object * F_call(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args));
if (p->type != ALISP_OBJ_IDENTIFIER && p->type != ALISP_OBJ_STRING) {
lisp_warn(instance, "expected an function name");
return &alsa_lisp_nil;
}
return eval_cons1(instance, p, cdr(args));
}
/*
* Syntax: (int value)
* 'value' can be integer or float type
@ -1968,9 +1996,9 @@ struct alisp_object * F_int(struct alisp_instance *instance, struct alisp_object
{
struct alisp_object * p = eval(instance, car(args));
if (p->type == ALISP_INTEGER)
if (p->type == ALISP_OBJ_INTEGER)
return p;
if (p->type == ALISP_FLOAT)
if (p->type == ALISP_OBJ_FLOAT)
return new_integer(instance, floor(p->value.f));
lisp_warn(instance, "expected an integer or float for integer conversion");
@ -1985,9 +2013,9 @@ struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_obje
{
struct alisp_object * p = eval(instance, car(args));
if (p->type == ALISP_FLOAT)
if (p->type == ALISP_OBJ_FLOAT)
return p;
if (p->type == ALISP_INTEGER)
if (p->type == ALISP_OBJ_INTEGER)
return new_float(instance, p->value.i);
lisp_warn(instance, "expected an integer or float for integer conversion");
@ -2002,9 +2030,9 @@ struct alisp_object * F_str(struct alisp_instance *instance, struct alisp_object
{
struct alisp_object * p = eval(instance, car(args));
if (p->type == ALISP_STRING)
if (p->type == ALISP_OBJ_STRING)
return p;
if (p->type == ALISP_INTEGER || p->type == ALISP_FLOAT) {
if (p->type == ALISP_OBJ_INTEGER || p->type == ALISP_OBJ_FLOAT) {
char buf[64];
if (p->type == ALISP_INTEGER) {
snprintf(buf, sizeof(buf), "%ld", p->value.i);
@ -2166,6 +2194,7 @@ struct intrinsic {
};
static struct intrinsic intrinsics[] = {
{ "!=", F_numneq },
{ "%", F_mod },
{ "&dump-memory", F_dump_memory },
{ "&dump-objects", F_dump_objects },
@ -2183,6 +2212,7 @@ static struct intrinsic intrinsics[] = {
{ "assoc", F_assoc },
{ "assq", F_assq },
{ "atom", F_atom },
{ "call", F_call },
{ "car", F_car },
{ "cdr", F_cdr },
{ "cond", F_cond },
@ -2233,18 +2263,11 @@ static int compar(const void *p1, const void *p2)
((struct intrinsic *)p2)->name);
}
static struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p)
static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
{
struct alisp_object * p1 = car(p), * p2 = cdr(p), * p3;
if (p1 != &alsa_lisp_nil && p1->type == ALISP_OBJ_IDENTIFIER) {
struct alisp_object * p3;
struct intrinsic key, *item;
if (!strcmp(p1->value.id, "lambda"))
return p;
auto_garbage_collect(instance);
key.name = p1->value.id;
if ((item = bsearch(&key, intrinsics,
sizeof intrinsics / sizeof intrinsics[0],
@ -2260,6 +2283,21 @@ static struct alisp_object * eval_cons(struct alisp_instance *instance, struct a
return eval_func(instance, p3, p2);
else
lisp_warn(instance, "function `%s' is undefined", p1->value.id);
return &alsa_lisp_nil;
}
static inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p)
{
struct alisp_object * p1 = car(p);
if (p1 != &alsa_lisp_nil && p1->type == ALISP_OBJ_IDENTIFIER) {
if (!strcmp(p1->value.id, "lambda"))
return p;
auto_garbage_collect(instance);
return eval_cons1(instance, p1, cdr(p));
}
return &alsa_lisp_nil;
@ -2655,8 +2693,8 @@ int alsa_lisp_seq_pointer(struct alisp_seq_iterator *seq, const char *ptr_id, vo
{
struct alisp_object * p2;
if (seq->type == ALISP_OBJ_CONS && seq->value.c.cdr->type == ALISP_OBJ_CONS)
seq = seq->value.c.cdr;
if (seq->type == ALISP_OBJ_CONS && seq->value.c.car->type == ALISP_OBJ_CONS)
seq = seq->value.c.car;
if (seq->type == ALISP_OBJ_CONS) {
p2 = seq->value.c.car;
if (p2->type != ALISP_OBJ_STRING)

View file

@ -188,11 +188,6 @@ static struct alisp_object * add_cons2(struct alisp_instance * instance, struct
return lexpr;
}
static inline struct alisp_object * new_result(struct alisp_instance * instance, int err)
{
return new_integer(instance, err);
}
static struct alisp_object * new_result1(struct alisp_instance * instance, int err, const char *ptr_id, void *ptr)
{
struct alisp_object * lexpr, * p1;
@ -254,6 +249,7 @@ static struct alisp_object * new_result3(struct alisp_instance * instance, int e
typedef int (*snd_int_pp_strp_int_t)(void **rctl, const char *name, int mode);
typedef int (*snd_int_pp_p_t)(void **rctl, void *handle);
typedef int (*snd_int_p_t)(void *rctl);
typedef char * (*snd_str_p_t)(void *rctl);
typedef int (*snd_int_intp_t)(int *val);
typedef int (*snd_int_str_t)(const char *str);
typedef int (*snd_int_int_strp_t)(int val, char **str);
@ -328,7 +324,18 @@ static struct alisp_object * FA_int_p(struct alisp_instance * instance, struct a
handle = (void *)get_ptr(args, item->prefix);
if (handle == NULL)
return &alsa_lisp_nil;
return new_result(instance, ((snd_int_p_t)item->xfunc)(handle));
return new_integer(instance, ((snd_int_p_t)item->xfunc)(handle));
}
static struct alisp_object * FA_str_p(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
{
void *handle;
args = eval(instance, car(args));
handle = (void *)get_ptr(args, item->prefix);
if (handle == NULL)
return &alsa_lisp_nil;
return new_string(instance, ((snd_str_p_t)item->xfunc)(handle));
}
static struct alisp_object * FA_int_intp(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
@ -351,7 +358,7 @@ static struct alisp_object * FA_int_str(struct alisp_instance * instance, struct
if (args->type != ALISP_OBJ_STRING && args->type != ALISP_OBJ_IDENTIFIER)
return &alsa_lisp_nil;
err = ((snd_int_str_t)item->xfunc)(args->value.s);
return new_result(instance, err);
return new_integer(instance, err);
}
static struct alisp_object * FA_int_int_strp(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
@ -606,7 +613,7 @@ static struct alisp_object * FA_hctl_elem_write(struct alisp_instance * instance
snd_ctl_elem_value_alloca(&value);
err = snd_hctl_elem_info(handle, info);
if (err < 0)
return new_result(instance, err);
return new_integer(instance, err);
type = snd_ctl_elem_info_get_type(info);
count = snd_ctl_elem_info_get_count(info);
if (type == SND_CTL_ELEM_TYPE_IEC958) {
@ -641,7 +648,7 @@ static struct alisp_object * FA_hctl_elem_write(struct alisp_instance * instance
p1 = cdr(p1);
} while (p1 != &alsa_lisp_nil);
err = snd_hctl_elem_write(handle, value);
return new_result(instance, err);
return new_integer(instance, err);
}
static struct alisp_object * FA_pcm_info(struct alisp_instance * instance, struct acall_table * item, struct alisp_object * args)
@ -701,6 +708,7 @@ static struct acall_table acall_table[] = {
{ "hctl_open", &FA_int_pp_strp_int, (void *)&snd_hctl_open, "hctl" },
{ "hctl_open_ctl", &FA_int_pp_p, (void *)&snd_hctl_open_ctl, "hctl" },
{ "pcm_info", &FA_pcm_info, NULL, "pcm" },
{ "pcm_name", &FA_str_p, (void *)&snd_pcm_name, "pcm" },
};
static int acall_compar(const void *p1, const void *p2)

View file

@ -1,3 +1,7 @@
;
; Toplevel configuration for the ALSA Ordinary Mixer Interface
;
(defun sndo_include (hctl stream)
(setq info (Acall "ctl_card_info" (Acall "hctl_ctl" hctl)))
(if (= (Aerror info) 0)
@ -7,75 +11,78 @@
(setq file (+ (path "data") "/alsa/cards/" (snd_card_alias driver) "/sndo" stream "-mixer.alisp"))
(setq r (include file))
(when (= r -2) (Asyserr "unable to find file " file))
(unsetq driver file r)
)
(setq r (Aerror info))
(unsetq info r)
)
(unsetq info driver file r)
)
(defun sndo_mixer_open_fcn (stream)
(setq fcn (+ "sndo" stream "_mixer_open"))
(setq r (if (exfun fcn) (call fcn hctl) 0))
(when (= r 0)
(setq hctls (if hctls (cons hctls (cons hctl)) hctl))
)
(unsetq fcn r)
)
(defun sndo_mixer_open_hctl (card stream)
(setq hctl (Acall "hctl_open" (+ "hw:" (str card)) nil))
(setq r (Aerror hctl))
(when (= r 0)
(setq hctl (Aresult hctl))
(setq r (sndo_include hctl stream))
(when (= r 0) (setq r (sndo_mixer_open_fcn stream)))
)
(unsetq hctl r)
)
(defun sndo_mixer_open_virtual (pcm stream)
(setq name (Acall "pcm_name" pcm))
(setq file (+ (path "data") "/alsa/virtual/" name "/sndo" stream "-mixer.alisp"))
(setq r (include file))
(when (= r -2) (Asyserr "unable to find file " file))
(when (= r 0) (setq r (sndo_mixer_open_fcn stream)))
(unsetq name file r)
)
(defun sndo_mixer_open1 (pcm stream)
(setq info (Acall "pcm_info" pcm))
(setq r (Aerror info))
(when (= r 0)
(progn
(setq info (Aresult info))
(setq card (cdr (assq "card" info)))
(setq r
(if (< card 0)
(+ (Acall "pcm_name" pcm) stream)
(+ "hw:" (str card))
(sndo_mixer_open_virtual pcm stream)
(sndo_mixer_open_hctl card stream)
)
)
(unsetq card)
)
)
(unsetq info r)
(unsetq info card r)
)
(defun sndo_mixer_open (ppcm cpcm)
(setq pname (sndo_mixer_open1 ppcm "p"))
(setq cname (sndo_mixer_open1 cpcm "c"))
(setq phctl (Acall "hctl_open" pname nil))
(if (= (Aerror phctl) 0)
(progn
(setq phctl (Aresult phctl))
(setq chctl (Acall "hctl_open" cname nil))
(if (= (Aerror chctl) 0)
(progn
(setq chctl (Aresult chctl))
(setq hctls (cons phctl (cons chctl)))
(setq r (sndo_include phctl "p"))
(when (= r 0) (setq r (sndo_include chctl "c")))
(when (= r 0) (setq r (if (exfun sndop_mixer_open) (sndop_mixer_open phctl) 0)))
(when (= r 0)
(progn
(setq r (if (exfun sndoc_mixer_open) (sndoc_mixer_open chctl) 0))
(unless (= r 0) (sndop_close phctl))
)
)
(unless (= r 0) (sndo_close))
(unsetq phctl chctl)
(gc)
(setq r (sndo_mixer_open1 ppcm "p"))
(when (= r 0) (setq r (sndo_mixer_open1 cpcm "c")))
(when (!= r 0) (sndo_mixer_close))
(unsetq r)
)
(defun sndo_mixer_close1 (hctl stream)
(when hctl
(progn
(Acall "hctl_close" (Aresult phctl))
(setq r (Aerror chctl))
(unsetq r)
(setq fcn (+ "sndo" stream "_mixer_close"))
(when (exfun fcn) (call fcn hctl))
(unsetq fcn)
(Acall "hctl_close" hctl)
)
)
)
(setq r (Aerror phctl))
(unsetq r)
)
)
(defun sndo_mixer_close nil
(cond (exfun sndop_close) (sndop_close (nth 0 hctls)))
(cond (exfun sndoc_close) (sndoc_close (nth 1 hctls)))
(Acall "hctl_close" (nth 0 hctls))
(Acall "hctl_close" (nth 1 hctls))
(sndo_mixer_close1 (nth 1 hctls) "c")
(sndo_mixer_close1 (nth 0 hctls) "p")
(unsetq hctls)
)

View file

@ -184,6 +184,20 @@ int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned in
return snd_ctl_poll_descriptors(hctl->ctl, pfds, space);
}
/**
* \brief get returned events from poll descriptors
* \param ctl HCTL handle
* \param pfds array of poll descriptors
* \param nfds count of poll descriptors
* \param revents returned events
* \return zero if success, otherwise a negative error code
*/
int snd_hctl_poll_descriptors_revents(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
assert(hctl);
return snd_ctl_poll_descriptors_revents(hctl->ctl, pfds, nfds, revents);
}
static int snd_hctl_throw_event(snd_hctl_t *hctl, unsigned int mask,
snd_hctl_elem_t *elem)
{

View file

@ -206,8 +206,27 @@ int sndo_mixer_poll_descriptors_count(sndo_mixer_t *mixer)
*/
int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space)
{
//return snd_mixer_poll_descriptors(mixer->mixer, pfds, space);
return -ENODEV;
int err, idx, res;
if (mixer->hctl_count > 0) {
for (idx = res = 0; idx < mixer->hctl_count && space > 0; idx++) {
err = snd_hctl_poll_descriptors(mixer->hctl[idx], pfds, space);
if (err < 0)
return err;
res += err;
space -= err;
}
return res;
} else {
struct alisp_seq_iterator *result;
long val;
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_poll_descriptors", "%i", space);
if (err < 0)
return err;
assert(0); /* FIXME: pass pfds to application */
err = alsa_lisp_seq_integer(result, &val);
return err < 0 ? err : val;
}
}
/**
@ -220,8 +239,120 @@ int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsign
*/
int sndo_mixer_poll_descriptors_revents(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
//return snd_mixer_poll_descriptors_revents(mixer->mixer, pfds, nfds, revents);
return -ENODEV;
int err, idx, count, res;
if (mixer->hctl_count > 0) {
for (idx = res = 0; idx < mixer->hctl_count && nfds > 0; idx++) {
err = snd_hctl_poll_descriptors_count(mixer->hctl[idx]);
if (err < 0)
return err;
count = err;
if (nfds < (unsigned int)err)
return -EINVAL;
err = snd_hctl_poll_descriptors_revents(mixer->hctl[idx], pfds, count, revents);
if (err < 0)
return err;
if (err != count)
return -EINVAL;
pfds += count;
nfds -= err;
revents += count;
res += count;
}
return res;
} else {
struct alisp_seq_iterator *result;
long val, tmp;
assert(0); /* FIXME: pass pfds to alisp too */
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_poll_descriptors_revents", "%i", nfds);
if (err < 0)
return err;
err = alsa_lisp_seq_integer(result, &val);
if (err >= 0 && alsa_lisp_seq_count(result) > 1) {
alsa_lisp_seq_next(&result);
err = alsa_lisp_seq_integer(result, &tmp);
*revents = tmp;
} else {
*revents = 0;
}
return err < 0 ? err : val;
}
}
#define IOLINES 6
static const char *name_table1[] = {
"Master",
"PCM",
"Line",
"Mic"
"CD",
"AUX"
};
#define SPEAKERS 14
static const char *name_table2[] = {
"Front Left",
"Front Center Left",
"Front Center",
"Front Center Right",
"Front Right",
"Front Side Left",
"Front Side Right",
"Rear Side Left",
"Rear Side Right",
"Rear Left",
"Rear Center",
"Rear Right",
"LFE (Subwoofer)",
"Overhead"
};
#define CSOURCES 5
static const char *name_table3[] = {
"Mic",
"Line",
"CD",
"AUX",
"Mix",
};
static int compose_string(char **result, const char *s1, const char *s2, const char *s3, const char *s4)
{
int len = strlen(s1) + strlen(s2) + strlen(s3) + strlen(s4);
*result = malloc(len + 1);
if (*result == NULL)
return -ENOMEM;
strcpy(*result, s1);
strcat(*result, s2);
strcat(*result, s3);
strcat(*result, s4);
return 0;
}
/**
* \brief get ordinary mixer io control value
* \param mixer ordinary mixer handle
* \param type io type
* \param val returned value
* \return zero if success, otherwise a negative error code
*/
int sndo_mixer_io_get_name(enum sndo_mixer_io_type type, char **name)
{
if (type < IOLINES * 0x40) {
int tmp = type / 0x40;
type %= 0x40;
if (type < SPEAKERS)
return compose_string(name, name_table1[tmp], " ", name_table2[type], " Volume");
} else if (type >= SNDO_MIO_CGAIN_FL && type < SNDO_MIO_CGAIN_FL + SPEAKERS) {
return compose_string(name, "Capture Gain ", name_table2[type - SNDO_MIO_CGAIN_FL], "", "");
} else if (type >= SNDO_MIO_CSOURCE_MIC && type < SNDO_MIO_CSOURCE_MIC + CSOURCES) {
return compose_string(name, "Capture Source ", name_table3[type - SNDO_MIO_CSOURCE_MIC], "", "");
}
return -ENOENT;
}
/**
@ -233,7 +364,18 @@ int sndo_mixer_poll_descriptors_revents(sndo_mixer_t *mixer, struct pollfd *pfds
*/
int sndo_mixer_io_get(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
{
return -ENODEV;
struct alisp_seq_iterator *result;
long val1;
int err;
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_set", "%i", type);
if (err < 0)
return err;
err = alsa_lisp_seq_integer(result, &val1);
if (err < 0)
return err;
*val = val1;
return 0;
}
/**
@ -243,9 +385,118 @@ int sndo_mixer_io_get(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *va
* \param val desired value
* \return zero if success, otherwise a negative error code
*/
int sndo_mixer_io_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int val)
int sndo_mixer_io_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
{
return -ENODEV;
struct alisp_seq_iterator *result;
long val1;
int err;
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_set", "%i%i", type, *val);
if (err < 0)
return err;
err = alsa_lisp_seq_integer(result, &val1);
if (err < 0)
return err;
*val = val1;
return 0;
}
/**
* \brief try to set ordinary mixer io control value
* \param mixer ordinary mixer handle
* \param type io type
* \param val desired value
* \return zero if success, otherwise a negative error code
*
* This function does not update the value.
* It only returns the real value which will be set.
*/
int sndo_mixer_io_try_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
{
struct alisp_seq_iterator *result;
long val1;
int err;
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_try_set", "%i%i", type, *val);
if (err < 0)
return err;
err = alsa_lisp_seq_integer(result, &val1);
if (err < 0)
return err;
*val = val1;
return 0;
}
/**
* \brief get ordinary mixer io control value in dB (decibel units)
* \param mixer ordinary mixer handle
* \param type io type
* \param val returned value in dB
* \return zero if success, otherwise a negative error code
*/
int sndo_mixer_io_get_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
{
struct alisp_seq_iterator *result;
long val1;
int err;
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_set_dB", "%i", type);
if (err < 0)
return err;
err = alsa_lisp_seq_integer(result, &val1);
if (err < 0)
return err;
*val = val1;
return 0;
}
/**
* \brief set ordinary mixer io control value in dB (decibel units)
* \param mixer ordinary mixer handle
* \param type io type
* \param val desired value in dB
* \return zero if success, otherwise a negative error code
*/
int sndo_mixer_io_set_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
{
struct alisp_seq_iterator *result;
long val1;
int err;
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_set", "%i%i", type, *val);
if (err < 0)
return err;
err = alsa_lisp_seq_integer(result, &val1);
if (err < 0)
return err;
*val = val1;
return 0;
}
/**
* \brief try to set ordinary mixer io control value in dB (decibel units)
* \param mixer ordinary mixer handle
* \param type io type
* \param val desired and returned value in dB
* \return zero if success, otherwise a negative error code
*
* This function does not update the value.
* It only returns the real value which will be set.
*/
int sndo_mixer_io_try_set_dB(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int *val)
{
struct alisp_seq_iterator *result;
long val1;
int err;
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_try_set", "%i%i", type, *val);
if (err < 0)
return err;
err = alsa_lisp_seq_integer(result, &val1);
if (err < 0)
return err;
*val = val1;
return 0;
}
/**
@ -257,5 +508,25 @@ int sndo_mixer_io_set(sndo_mixer_t *mixer, enum sndo_mixer_io_type type, int val
*/
int sndo_mixer_io_change(sndo_mixer_t *mixer, enum sndo_mixer_io_type *changed, int changed_array_size)
{
return -ENODEV;
struct alisp_seq_iterator *result;
long val1;
int err;
err = alsa_lisp_function(mixer->alisp, &result, "sndo_mixer_io_change", "%i", changed_array_size);
if (err < 0)
return err;
err = alsa_lisp_seq_integer(result, &val1);
if (err < 0)
return err;
if (val1 < 0)
return val1;
while (changed_array_size-- > 0) {
*changed = val1;
if (!alsa_lisp_seq_next(&result))
break;
err = alsa_lisp_seq_integer(result, &val1);
if (err < 0)
return err;
}
return 0;
}

View file

@ -11,11 +11,11 @@
static void help(void)
{
printf(
"Usage: omixer [OPTION]...\n"
"Usage: omixer [OPTION]...\n\n"
"-h,--help help\n"
"-P,--pname playback PCM device\n"
"-C,--cname capture PCM device\n"
"\n");
);
}
int main(int argc, char *argv[])