From: Jaroslav Kysela Date: Mon, 13 Oct 2003 12:06:45 +0000 (+0000) Subject: More changes to the ordinary mixer API X-Git-Tag: v1.0.3~91 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=ab61b62cb487bc305762bc800d0a3b6751f610d3;p=alsa-lib.git More changes to the ordinary mixer API --- diff --git a/include/control.h b/include/control.h index a40c125e..73c10b36 100644 --- a/include/control.h +++ b/include/control.h @@ -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); diff --git a/include/mixer_ordinary.h b/include/mixer_ordinary.h index eebce24f..0c25dc20 100644 --- a/include/mixer_ordinary.h +++ b/include/mixer_ordinary.h @@ -29,6 +29,25 @@ #include +/* + * 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, - - /** 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) */ + SNDO_MIO_MASTER_OVRVOL, + + /* 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, - - /** 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) */ + SNDO_MIO_PCM_OVRVOL, + + /* 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, - - /** 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) */ + SNDO_MIO_LINE_OVRVOL, + + /* 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, - - /** 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) */ + SNDO_MIO_MIC_OVRVOL, + + /* 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 source - MIC exclusive switch (0 = off, 1 = on) */ - SNDO_MIO_CSOURCE_MIC = 0x1100, - /** capture source - LINE exclusive switch (0 = off, 1 = on) */ + /* 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 (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); /** \} */ diff --git a/src/Versions b/src/Versions index d9919cf5..aedaff9a 100644 --- a/src/Versions +++ b/src/Versions @@ -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; diff --git a/src/alisp/alisp.c b/src/alisp/alisp.c index 4e8b2bf0..0522a399 100644 --- a/src/alisp/alisp.c +++ b/src/alisp/alisp.c @@ -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,33 +2263,41 @@ 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; + struct alisp_object * p3; + struct intrinsic key, *item; - if (p1 != &alsa_lisp_nil && p1->type == ALISP_OBJ_IDENTIFIER) { - struct intrinsic key, *item; + key.name = p1->value.id; + if ((item = bsearch(&key, intrinsics, + sizeof intrinsics / sizeof intrinsics[0], + sizeof intrinsics[0], compar)) != NULL) + return item->func(instance, p2); - if (!strcmp(p1->value.id, "lambda")) - return p; + if ((item = bsearch(&key, snd_intrinsics, + sizeof snd_intrinsics / sizeof snd_intrinsics[0], + sizeof snd_intrinsics[0], compar)) != NULL) + return item->func(instance, p2); - auto_garbage_collect(instance); + if ((p3 = get_object(instance, p1)) != &alsa_lisp_nil) + return eval_func(instance, p3, p2); + else + lisp_warn(instance, "function `%s' is undefined", p1->value.id); - key.name = p1->value.id; - if ((item = bsearch(&key, intrinsics, - sizeof intrinsics / sizeof intrinsics[0], - sizeof intrinsics[0], compar)) != NULL) - return item->func(instance, p2); + return &alsa_lisp_nil; +} - if ((item = bsearch(&key, snd_intrinsics, - sizeof snd_intrinsics / sizeof snd_intrinsics[0], - sizeof snd_intrinsics[0], compar)) != NULL) - return item->func(instance, p2); +static inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p) +{ + struct alisp_object * p1 = car(p); - if ((p3 = get_object(instance, p1)) != &alsa_lisp_nil) - return eval_func(instance, p3, p2); - else - lisp_warn(instance, "function `%s' is undefined", p1->value.id); + 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) diff --git a/src/alisp/alisp_snd.c b/src/alisp/alisp_snd.c index 6c12c9cc..3bfe1c9c 100644 --- a/src/alisp/alisp_snd.c +++ b/src/alisp/alisp_snd.c @@ -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) diff --git a/src/conf/sndo-mixer.alisp b/src/conf/sndo-mixer.alisp index 8342ad05..3b3ffdf3 100644 --- a/src/conf/sndo-mixer.alisp +++ b/src/conf/sndo-mixer.alisp @@ -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)) - ) + (setq info (Aresult info)) + (setq card (cdr (assq "card" info))) + (setq r + (if (< card 0) + (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) + (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 - (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) - (unsetq r) - ) - (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) ) diff --git a/src/control/hcontrol.c b/src/control/hcontrol.c index b1d5ac42..3779fc80 100644 --- a/src/control/hcontrol.c +++ b/src/control/hcontrol.c @@ -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) { diff --git a/src/ordinary_mixer/ordinary_mixer.c b/src/ordinary_mixer/ordinary_mixer.c index 63042923..9443a04a 100644 --- a/src/ordinary_mixer/ordinary_mixer.c +++ b/src/ordinary_mixer/ordinary_mixer.c @@ -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) +{ + 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) { - return -ENODEV; + 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; } diff --git a/test/omixer.c b/test/omixer.c index 0512b7eb..1f4b2e1c 100644 --- a/test/omixer.c +++ b/test/omixer.c @@ -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[])