ALISP update

- function names are more emacs-like
 - implemented (format) function
 - fixed numerous memory-leaks (valgrind is now happy)
Ordinary mixer
 - added the global view (using hdsp names only)
This commit is contained in:
Jaroslav Kysela 2003-12-23 16:42:55 +00:00
parent beb837bcf7
commit d0facfde2b
10 changed files with 628 additions and 250 deletions

View file

@ -3,7 +3,7 @@
; The test is indended to find memory leaks. ; The test is indended to find memory leaks.
; ;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz> ; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
; License: GPL ; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
; ;
; ;
@ -120,7 +120,7 @@
(atom "one") (&check-memory) (atom "one") (&check-memory)
(atom "one" 'two) (&check-memory) (atom "one" 'two) (&check-memory)
(call) (&check-memory) (funcall) (&check-memory)
(car) (&check-memory) (car) (&check-memory)
(car '(one . two)) (&check-memory) (car '(one . two)) (&check-memory)
@ -128,6 +128,13 @@
(cdr) (&check-memory) (cdr) (&check-memory)
(cdr '(one . two)) (&check-memory) (cdr '(one . two)) (&check-memory)
(concat) (&check-memory)
(concat 'aaaa) (&check-memory)
(concat 'aaaa 'bbbb) (&check-memory)
(concat "aaaa") (&check-memory)
(concat "aaaa" "bbbb") (&check-memory)
(concat "aaaa" "bbbb" "cccc") (&check-memory)
(cond) (&check-memory) (cond) (&check-memory)
(cond 0) (&check-memory) (cond 0) (&check-memory)
(cond 0 1) (&check-memory) (cond 0 1) (&check-memory)
@ -160,11 +167,17 @@
(exfun 'abcd) (&check-memory) (exfun 'abcd) (&check-memory)
(exfun 'abcd 'ijkl) (&check-memory) (exfun 'abcd 'ijkl) (&check-memory)
(float) (&check-memory) (format) (&check-memory)
(float 1) (&check-memory) (format 1) (&check-memory)
(float 'a) (&check-memory) (format 'a) (&check-memory)
(float "a" "b" "c") (&check-memory) (format "a" "b" "c") (&check-memory)
(float "1.2") (&check-memory) (format "1.2") (&check-memory)
(format "%c" 43) (&check-memory)
(format "%d" 12) (&check-memory)
(format "%i" 12) (&check-memory)
(format "%f" 12.1) (&check-memory)
(format "%s" "abcd") (&check-memory)
(format "%s %i %i" "abcd" 1 2) (&check-memory)
(garbage-collect) (&check-memory) (garbage-collect) (&check-memory)
(gc) (&check-memory) (gc) (&check-memory)
@ -179,12 +192,6 @@
(include "itest.lisp") (&check-memory) (include "itest.lisp") (&check-memory)
(int) (&check-memory)
(int 1) (&check-memory)
(int 'a) (&check-memory)
(int "a" "b" "c") (&check-memory)
(int "1.2") (&check-memory)
(list) (&check-memory) (list) (&check-memory)
(list "a") (&check-memory) (list "a") (&check-memory)
(list "a" "b") (&check-memory) (list "a" "b") (&check-memory)
@ -267,10 +274,28 @@
(setq a 1) (unsetq a) (&check-memory) (setq a 1) (unsetq a) (&check-memory)
(setq a 1 2) (unsetq a) (&check-memory) (setq a 1 2) (unsetq a) (&check-memory)
(str) (&check-memory) (string-equal) (&check-memory)
(str 1) (&check-memory) (string-equal 1) (&check-memory)
(str 1 2 3) (&check-memory) (string-equal "a") (&check-memory)
(str 1.2 1.3) (&check-memory) (string-equal "a" "a") (&check-memory)
(string-equal "a" "b") (&check-memory)
(string-equal "a" "b" "c") (&check-memory)
(string-to-integer) (&check-memory)
(string-to-integer 1) (&check-memory)
(string-to-integer 1.5) (&check-memory)
(string-to-integer "a") (&check-memory)
(string-to-integer "a" "a") (&check-memory)
(string-to-integer "a" "b") (&check-memory)
(string-to-integer "a" "b" "c") (&check-memory)
(string-to-float) (&check-memory)
(string-to-float 1) (&check-memory)
(string-to-float 1.5) (&check-memory)
(string-to-float "a") (&check-memory)
(string-to-float "a" "a") (&check-memory)
(string-to-float "a" "b") (&check-memory)
(string-to-float "a" "b" "c") (&check-memory)
(string=) (&check-memory) (string=) (&check-memory)
(string= 1) (&check-memory) (string= 1) (&check-memory)
@ -279,13 +304,6 @@
(string= "a" "b") (&check-memory) (string= "a" "b") (&check-memory)
(string= "a" "b" "c") (&check-memory) (string= "a" "b" "c") (&check-memory)
(string-equal) (&check-memory)
(string-equal 1) (&check-memory)
(string-equal "a") (&check-memory)
(string-equal "a" "a") (&check-memory)
(string-equal "a" "b") (&check-memory)
(string-equal "a" "b" "c") (&check-memory)
(unless) (&check-memory) (unless) (&check-memory)
(unless 1) (&check-memory) (unless 1) (&check-memory)
(unless 0 1 2) (&check-memory) (unless 0 1 2) (&check-memory)
@ -322,27 +340,31 @@
(unsetq abcd) (unsetq abcd)
(&check-memory) (&check-memory)
(setq abcd (("abcd" . "efgh") ("1234" . "5678")))
(unsetq abcd)
(&check-memory)
(defun myfun () (princ "a\n")) (defun myfun () (princ "a\n"))
(exfun 'myfun) (exfun 'myfun)
(unsetq myfun) (unsetq myfun)
(&check-memory) (&check-memory)
(defun myfun () (princ "a\n")) (defun myfun () (princ "a\n"))
(call 'myfun) (funcall 'myfun)
(call 'myfun 'aaaaa) (funcall 'myfun 'aaaaa)
(unsetq myfun) (unsetq myfun)
(&check-memory) (&check-memory)
(defun myfun (o) (princ o "a\n")) (defun myfun (o) (princ o "a\n"))
(call 'myfun) (funcall 'myfun)
(call 'myfun 'aaaaa) (funcall 'myfun 'aaaaa)
(unsetq myfun) (unsetq myfun)
(&check-memory) (&check-memory)
(defun myfun (o p) (princ o p "\n")) (defun myfun (o p) (princ o p "\n"))
(call 'myfun) (funcall 'myfun)
(call 'myfun 'aaaaa) (funcall 'myfun 'aaaaa)
(call 'myfun 'aaaaa 'bbbbb) (funcall 'myfun 'aaaaa 'bbbbb)
(unsetq myfun) (unsetq myfun)
(&check-memory) (&check-memory)

View file

@ -45,6 +45,8 @@ int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterato
__attribute__ ((format (printf, 4, 5))) __attribute__ ((format (printf, 4, 5)))
#endif #endif
; ;
void alsa_lisp_result_free(struct alisp_instance *instance,
struct alisp_seq_iterator *result);
int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id, int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
struct alisp_seq_iterator **seq); struct alisp_seq_iterator **seq);
int alsa_lisp_seq_next(struct alisp_seq_iterator **seq); int alsa_lisp_seq_next(struct alisp_seq_iterator **seq);

View file

@ -195,7 +195,8 @@ extern "C" {
* \{ * \{
*/ */
int sndo_mixer_open(sndo_mixer_t **pmixer, snd_pcm_t *playback_pcm, snd_pcm_t *capture_pcm, struct alisp_cfg *lconf); int sndo_mixer_open(sndo_mixer_t **pmixer, const char *playback_name, const char *capture_name, struct alisp_cfg *lconf);
int sndo_mixer_open_pcm(sndo_mixer_t **pmixer, snd_pcm_t *playback_pcm, snd_pcm_t *capture_pcm, struct alisp_cfg *lconf);
int sndo_mixer_close(sndo_mixer_t *mixer); int sndo_mixer_close(sndo_mixer_t *mixer);
int sndo_mixer_poll_descriptors_count(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(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space);

View file

@ -46,11 +46,11 @@ 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_cons(snd_output_t *out, struct alisp_object * p);
static void princ_object(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(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 */ /* functions */
static struct alisp_object *F_eval(struct alisp_instance *instance, struct alisp_object *); static struct alisp_object *F_eval(struct alisp_instance *instance, struct alisp_object *);
static struct alisp_object *F_progn(struct alisp_instance *instance, struct alisp_object *); static struct alisp_object *F_progn(struct alisp_instance *instance, struct alisp_object *);
static struct alisp_object *F_funcall(struct alisp_instance *instance, struct alisp_object *);
/* others */ /* others */
static int alisp_include_file(struct alisp_instance *instance, const char *filename); static int alisp_include_file(struct alisp_instance *instance, const char *filename);
@ -176,9 +176,7 @@ static void free_object(struct alisp_object * p)
static void delete_object(struct alisp_instance *instance, struct alisp_object * p) static void delete_object(struct alisp_instance *instance, struct alisp_object * p)
{ {
if (p == NULL) if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
return;
if (p == &alsa_lisp_nil || p == &alsa_lisp_t)
return; return;
if (alisp_compare_type(p, ALISP_OBJ_NIL) || if (alisp_compare_type(p, ALISP_OBJ_NIL) ||
alisp_compare_type(p, ALISP_OBJ_T)) alisp_compare_type(p, ALISP_OBJ_T))
@ -215,8 +213,8 @@ static void delete_tree(struct alisp_instance *instance, struct alisp_object * p
static struct alisp_object * incref_object(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * p) static struct alisp_object * incref_object(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * p)
{ {
if (p == NULL) if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t)
return NULL; return p;
if (alisp_get_refs(p) == ALISP_MAX_REFS) { if (alisp_get_refs(p) == ALISP_MAX_REFS) {
assert(0); assert(0);
fprintf(stderr, "OOPS: alsa lisp: incref fatal error\n"); fprintf(stderr, "OOPS: alsa lisp: incref fatal error\n");
@ -259,12 +257,30 @@ static void free_objects(struct alisp_instance *instance)
{ {
struct list_head *pos, *pos1; struct list_head *pos, *pos1;
struct alisp_object * p; struct alisp_object * p;
struct alisp_object_pair * pair;
int i, j; int i, j;
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) {
list_for_each_safe(pos, pos1, &instance->setobjs_list[i]) {
pair = list_entry(pos, struct alisp_object_pair, list);
lisp_debug(instance, "freeing pair: '%s' -> %p", pair->name, pair->value);
delete_tree(instance, pair->value);
free((void *)pair->name);
free(pair);
}
}
for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++) for (i = 0; i < ALISP_OBJ_PAIR_HASH_SIZE; i++)
for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++) { for (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++) {
list_for_each_safe(pos, pos1, &instance->used_objs_list[i][j]) { list_for_each_safe(pos, pos1, &instance->used_objs_list[i][j]) {
p = list_entry(pos, struct alisp_object, list); p = list_entry(pos, struct alisp_object, list);
lisp_warn(instance, "object %p is still referenced %i times!", p, alisp_get_refs(p));
#if 0
snd_output_printf(instance->wout, ">>>> ");
princ_object(instance->wout, p);
snd_output_printf(instance->wout, " <<<<\n");
#endif
if (alisp_get_refs(p) > 0)
alisp_set_refs(p, 1);
delete_object(instance, p); delete_object(instance, p);
} }
} }
@ -575,7 +591,7 @@ static int gettoken(struct alisp_instance *instance)
instance->thistoken = ALISP_INTEGER; instance->thistoken = ALISP_INTEGER;
do { do {
__ok: __ok:
if (p - instance->token_buffer >= instance->token_buffer_max) { if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p); p = extend_buf(instance, p);
if (p == NULL) if (p == NULL)
return instance->thistoken = EOF; return instance->thistoken = EOF;
@ -620,7 +636,7 @@ static int gettoken(struct alisp_instance *instance)
/* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */ /* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */
p = instance->token_buffer; p = instance->token_buffer;
do { do {
if (p - instance->token_buffer >= instance->token_buffer_max) { if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p); p = extend_buf(instance, p);
if (p == NULL) if (p == NULL)
return instance->thistoken = EOF; return instance->thistoken = EOF;
@ -636,7 +652,7 @@ static int gettoken(struct alisp_instance *instance)
/* String: "\""([^"]|"\\".)*"\"" */ /* String: "\""([^"]|"\\".)*"\"" */
p = instance->token_buffer; p = instance->token_buffer;
while ((c = xgetc(instance)) != '"' && c != EOF) { while ((c = xgetc(instance)) != '"' && c != EOF) {
if (p - instance->token_buffer >= instance->token_buffer_max) { if (p - instance->token_buffer >= instance->token_buffer_max - 1) {
p = extend_buf(instance, p); p = extend_buf(instance, p);
if (p == NULL) if (p == NULL)
return instance->thistoken = EOF; return instance->thistoken = EOF;
@ -683,24 +699,26 @@ static struct alisp_object * parse_form(struct alisp_instance *instance)
* Parse a dotted pair notation. * Parse a dotted pair notation.
*/ */
if (thistoken == '.') { if (thistoken == '.') {
thistoken = gettoken(instance); gettoken(instance);
if (prev == NULL) { if (prev == NULL) {
lisp_error(instance, "unexpected `.'"); lisp_error(instance, "unexpected '.'");
__err:
delete_tree(instance, first);
return NULL; return NULL;
} }
prev->value.c.cdr = parse_object(instance, 1); prev->value.c.cdr = parse_object(instance, 1);
if (prev->value.c.cdr == NULL) if (prev->value.c.cdr == NULL)
return NULL; goto __err;
if ((thistoken = gettoken(instance)) != ')') { if ((thistoken = gettoken(instance)) != ')') {
lisp_error(instance, "expected `)'"); lisp_error(instance, "expected ')'");
return NULL; goto __err;
} }
break; break;
} }
p = new_object(instance, ALISP_OBJ_CONS); p = new_object(instance, ALISP_OBJ_CONS);
if (p == NULL) if (p == NULL)
return NULL; goto __err;
if (first == NULL) if (first == NULL)
first = p; first = p;
@ -709,7 +727,8 @@ static struct alisp_object * parse_form(struct alisp_instance *instance)
p->value.c.car = parse_object(instance, 1); p->value.c.car = parse_object(instance, 1);
if (p->value.c.car == NULL) if (p->value.c.car == NULL)
return NULL; goto __err;
prev = p; prev = p;
} }
@ -724,11 +743,11 @@ static struct alisp_object * quote_object(struct alisp_instance *instance, struc
struct alisp_object * p; struct alisp_object * p;
if (obj == NULL) if (obj == NULL)
return NULL; goto __end1;
p = new_object(instance, ALISP_OBJ_CONS); p = new_object(instance, ALISP_OBJ_CONS);
if (p == NULL) if (p == NULL)
return NULL; goto __end1;
p->value.c.car = new_identifier(instance, "quote"); p->value.c.car = new_identifier(instance, "quote");
if (p->value.c.car == NULL) if (p->value.c.car == NULL)
@ -737,8 +756,9 @@ static struct alisp_object * quote_object(struct alisp_instance *instance, struc
if (p->value.c.cdr == NULL) { if (p->value.c.cdr == NULL) {
delete_object(instance, p->value.c.car); delete_object(instance, p->value.c.car);
__end: __end:
delete_object(instance, obj);
delete_object(instance, p); delete_object(instance, p);
__end1:
delete_tree(instance, obj);
return NULL; return NULL;
} }
@ -898,6 +918,7 @@ static struct alisp_object * unset_object(struct alisp_instance *instance, struc
if (!strcmp(p->name, id)) { if (!strcmp(p->name, id)) {
list_del(&p->list); list_del(&p->list);
res = p->value; res = p->value;
free((void *)p->name);
free(p); free(p);
return res; return res;
} }
@ -1117,74 +1138,78 @@ static struct alisp_object * F_cdr(struct alisp_instance *instance, struct alisp
static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args) static struct alisp_object * F_add(struct alisp_instance *instance, struct alisp_object * args)
{ {
struct alisp_object * p = args, * p1, * n; struct alisp_object * p = args, * p1, * n;
long v = 0;
double f = 0;
int type = ALISP_OBJ_INTEGER;
p1 = eval(instance, car(p)); p1 = eval(instance, car(p));
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) || for (;;) {
alisp_compare_type(p1, ALISP_OBJ_FLOAT)) { if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) {
long v = 0; if (type == ALISP_OBJ_FLOAT)
double f = 0; f += p1->value.i;
int type = ALISP_OBJ_INTEGER; else
for (;;) { v += p1->value.i;
if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) { } else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
if (type == ALISP_OBJ_FLOAT) f += p1->value.f + v;
f += p1->value.i; v = 0;
else type = ALISP_OBJ_FLOAT;
v += p1->value.i;
} else if (alisp_compare_type(p1, ALISP_OBJ_FLOAT)) {
f += p1->value.f + v;
v = 0;
type = ALISP_OBJ_FLOAT;
} else {
lisp_warn(instance, "sum with a non integer or float operand");
}
delete_tree(instance, p1);
p = cdr(n = p);
delete_object(instance, n);
if (p == &alsa_lisp_nil)
break;
p1 = eval(instance, car(p));
}
if (type == ALISP_OBJ_INTEGER) {
return new_integer(instance, v);
} else { } else {
return new_float(instance, f); lisp_warn(instance, "sum with a non integer or float operand");
} }
} else if (alisp_compare_type(p1, ALISP_OBJ_STRING)) { delete_tree(instance, p1);
char *str = NULL, *str1; p = cdr(n = p);
for (;;) { delete_object(instance, n);
if (alisp_compare_type(p1, ALISP_OBJ_STRING)) { if (p == &alsa_lisp_nil)
str1 = realloc(str, (str ? strlen(str) : 0) + strlen(p1->value.s) + 1); break;
if (str1 == NULL) { p1 = eval(instance, car(p));
nomem(); }
if (str) if (type == ALISP_OBJ_INTEGER) {
free(str); return new_integer(instance, v);
return NULL; } else {
} return new_float(instance, f);
if (str == NULL) }
strcpy(str1, p1->value.s); }
else
strcat(str1, p1->value.s); /*
str = str1; * Syntax: (concat expr...)
} else { */
lisp_warn(instance, "concat with a non string or identifier operand"); static struct alisp_object * F_concat(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = args, * p1, * n;
char *str = NULL, *str1;
p1 = eval(instance, car(p));
for (;;) {
if (alisp_compare_type(p1, ALISP_OBJ_STRING)) {
str1 = realloc(str, (str ? strlen(str) : 0) + strlen(p1->value.s) + 1);
if (str1 == NULL) {
nomem();
if (str)
free(str);
return NULL;
} }
delete_tree(instance, p1); if (str == NULL)
p = cdr(n = p); strcpy(str1, p1->value.s);
delete_object(instance, n); else
if (p == &alsa_lisp_nil) strcat(str1, p1->value.s);
break; str = str1;
p1 = eval(instance, car(p)); } else {
lisp_warn(instance, "concat with a non string or identifier operand");
} }
delete_tree(instance, p1);
p = cdr(n = p);
delete_object(instance, n);
if (p == &alsa_lisp_nil)
break;
p1 = eval(instance, car(p));
}
if (str) {
p = new_string(instance, str); p = new_string(instance, str);
free(str); free(str);
return p;
} else { } else {
lisp_warn(instance, "sum/concat with non-integer or string operand"); p = &alsa_lisp_nil;
delete_tree(instance, cdr(p));
delete_object(instance, p);
delete_tree(instance, p1);
} }
return &alsa_lisp_nil; return p;
} }
/* /*
@ -2218,6 +2243,7 @@ static struct alisp_object * F_unsetq(struct alisp_instance *instance, struct al
if (p1) if (p1)
delete_tree(instance, p1); delete_tree(instance, p1);
p1 = unset_object(instance, car(p)); p1 = unset_object(instance, car(p));
delete_tree(instance, car(p));
p = cdr(n = p); p = cdr(n = p);
delete_object(instance, n); delete_object(instance, n);
} while (p != &alsa_lisp_nil); } while (p != &alsa_lisp_nil);
@ -2269,7 +2295,7 @@ static struct alisp_object * F_defun(struct alisp_instance *instance, struct ali
static struct alisp_object * eval_func(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * args) static struct alisp_object * eval_func(struct alisp_instance *instance, struct alisp_object * p, struct alisp_object * args)
{ {
struct alisp_object * p1, * p2, * p3, * p4, * p5; struct alisp_object * p1, * p2, * p3, * p4;
struct alisp_object ** eval_objs, ** save_objs; struct alisp_object ** eval_objs, ** save_objs;
int i; int i;
@ -2297,9 +2323,8 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
i = 0; i = 0;
while (p3 != &alsa_lisp_nil) { while (p3 != &alsa_lisp_nil) {
eval_objs[i++] = eval(instance, car(p3)); eval_objs[i++] = eval(instance, car(p3));
p4 = cdr(p3); p3 = cdr(p4 = p3);
delete_object(instance, p3); delete_object(instance, p4);
p3 = p4;
} }
/* /*
@ -2307,48 +2332,49 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a
*/ */
i = 0; i = 0;
while (p2 != &alsa_lisp_nil) { while (p2 != &alsa_lisp_nil) {
p4 = car(p2); p3 = car(p2);
save_objs[i] = replace_object(instance, p4, eval_objs[i]); save_objs[i] = replace_object(instance, p3, eval_objs[i]);
if (save_objs[i] == NULL && if (save_objs[i] == NULL &&
set_object_direct(instance, p4, eval_objs[i]) == NULL) set_object_direct(instance, p3, eval_objs[i]) == NULL) {
p4 = NULL;
goto _end; goto _end;
}
p2 = cdr(p2); p2 = cdr(p2);
++i; ++i;
} }
p5 = F_progn(instance, incref_tree(instance, cdr(cdr(p)))); p4 = F_progn(instance, cdr(incref_tree(instance, p3 = cdr(p))));
/* /*
* Restore the old variable values. * Restore the old variable values.
*/ */
p2 = car(cdr(p)); p2 = car(p3);
delete_object(instance, p3);
i = 0; i = 0;
while (p2 != &alsa_lisp_nil) { while (p2 != &alsa_lisp_nil) {
p4 = car(p2); p3 = car(p2);
if (save_objs[i] == NULL) { if (save_objs[i] == NULL) {
p4 = unset_object(instance, p4); p3 = unset_object(instance, p3);
} else { } else {
p4 = replace_object(instance, p4, save_objs[i]); p3 = replace_object(instance, p3, save_objs[i]);
} }
i++; i++;
delete_tree(instance, p4); delete_tree(instance, p3);
p2 = cdr(p2); delete_tree(instance, car(p2));
p2 = cdr(p3 = p2);
delete_object(instance, p3);
} }
_end:
if (eval_objs) if (eval_objs)
free(eval_objs); free(eval_objs);
return p5; return p4;
} else { } else {
_delete: _delete:
delete_tree(instance, args); delete_tree(instance, args);
} }
return &alsa_lisp_nil; return &alsa_lisp_nil;
_end:
if (eval_objs)
free(eval_objs);
return NULL;
} }
struct alisp_object * F_gc(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args ATTRIBUTE_UNUSED) struct alisp_object * F_gc(struct alisp_instance *instance ATTRIBUTE_UNUSED, struct alisp_object * args ATTRIBUTE_UNUSED)
@ -2401,30 +2427,10 @@ struct alisp_object * F_include(struct alisp_instance *instance, struct alisp_ob
} }
/* /*
* Syntax: (call function args...) * Syntax: (string-to-integer value)
*/
struct alisp_object * F_call(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
!alisp_compare_type(p, ALISP_OBJ_STRING)) {
lisp_warn(instance, "expected an function name");
delete_tree(instance, p);
delete_tree(instance, cdr(args));
delete_object(instance, args);
return &alsa_lisp_nil;
}
p1 = cdr(args);
delete_object(instance, args);
return eval_cons1(instance, p, p1);
}
/*
* Syntax: (int value)
* 'value' can be integer or float type * 'value' can be integer or float type
*/ */
struct alisp_object * F_int(struct alisp_instance *instance, struct alisp_object * args) struct alisp_object * F_string_to_integer(struct alisp_instance *instance, struct alisp_object * args)
{ {
struct alisp_object * p = eval(instance, car(args)), * p1; struct alisp_object * p = eval(instance, car(args)), * p1;
@ -2443,10 +2449,10 @@ struct alisp_object * F_int(struct alisp_instance *instance, struct alisp_object
} }
/* /*
* Syntax: (float value) * Syntax: (string-to-float value)
* 'value' can be integer or float type * 'value' can be integer or float type
*/ */
struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_object * args) struct alisp_object * F_string_to_float(struct alisp_instance *instance, struct alisp_object * args)
{ {
struct alisp_object * p = eval(instance, car(args)), * p1; struct alisp_object * p = eval(instance, car(args)), * p1;
@ -2464,41 +2470,281 @@ struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_obje
return p1; return p1;
} }
/* static int append_to_string(char **s, int *len, char *from, int size)
* Syntax: (str value)
* 'value' can be integer, float or string type
*/
struct alisp_object * F_str(struct alisp_instance *instance, struct alisp_object * args)
{ {
struct alisp_object * p = eval(instance, car(args)), * p1; if (*len == 0) {
*s = malloc(*len = size + 1);
delete_tree(instance, cdr(args)); if (*s == NULL) {
delete_object(instance, args);
if (alisp_compare_type(p, ALISP_OBJ_STRING))
return p;
if (alisp_compare_type(p, ALISP_OBJ_INTEGER) ||
alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
char *buf = malloc(64);
if (buf == NULL) {
delete_tree(instance, p);
nomem(); nomem();
return NULL; return -ENOMEM;
} }
if (alisp_compare_type(p, ALISP_OBJ_INTEGER)) { memcpy(*s, from, size);
snprintf(buf, sizeof(buf), "%ld", p->value.i); } else {
} else { *len += size;
snprintf(buf, sizeof(buf), "%.f", p->value.f); *s = realloc(*s, *len);
} if (*s == NULL) {
p1 = new_string(instance, buf); nomem();
free(buf); return -ENOMEM;
}
memcpy(*s + strlen(*s), from, size);
}
(*s)[*len - 1] = '\0';
return 0;
}
static int format_parse_char(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
{
char b;
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "format: expected integer\n");
return 0;
}
b = p->value.i;
return append_to_string(s, len, &b, 1);
}
static int format_parse_integer(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
{
int res;
char *s1;
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
!alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
lisp_warn(instance, "format: expected integer or float\n");
return 0;
}
s1 = malloc(64);
if (s1 == NULL) {
nomem();
return -ENOMEM;
}
sprintf(s1, "%li", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? (long)floor(p->value.f) : p->value.i);
res = append_to_string(s, len, s1, strlen(s1));
free(s1);
return res;
}
static int format_parse_float(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
{
int res;
char *s1;
if (!alisp_compare_type(p, ALISP_OBJ_INTEGER) &&
!alisp_compare_type(p, ALISP_OBJ_FLOAT)) {
lisp_warn(instance, "format: expected integer or float\n");
return 0;
}
s1 = malloc(64);
if (s1 == NULL) {
nomem();
return -ENOMEM;
}
sprintf(s1, "%f", alisp_compare_type(p, ALISP_OBJ_FLOAT) ? p->value.f : (double)p->value.i);
res = append_to_string(s, len, s1, strlen(s1));
free(s1);
return res;
}
static int format_parse_string(struct alisp_instance *instance, char **s, int *len, struct alisp_object *p)
{
if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
lisp_warn(instance, "format: expected string\n");
return 0;
}
return append_to_string(s, len, p->value.s, strlen(p->value.s));
}
/*
* Syntax: (format format value...)
* 'format' is C-like format string
*/
struct alisp_object * F_format(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1 = cdr(args), * n;
char *s, *s1, *s2;
int len;
delete_object(instance, args);
if (!alisp_compare_type(p, ALISP_OBJ_STRING)) {
delete_tree(instance, p1);
delete_tree(instance, p);
lisp_warn(instance, "format: expected an format string");
return &alsa_lisp_nil;
}
s = p->value.s;
s1 = NULL;
len = 0;
n = eval(instance, car(p1));
do {
while (1) {
s2 = s;
while (*s2 && *s2 != '%')
s2++;
if (s2 != s) {
if (append_to_string(&s1, &len, s, s2 - s) < 0) {
__error:
delete_tree(instance, n);
delete_tree(instance, cdr(p1));
delete_object(instance, p1);
delete_tree(instance, p);
return NULL;
}
}
if (*s2 == '%')
s2++;
switch (*s2) {
case '%':
if (append_to_string(&s1, &len, s2, 1) < 0)
goto __error;
s = s2 + 1;
break;
case 'c':
if (format_parse_char(instance, &s1, &len, n) < 0)
goto __error;
s = s2 + 1;
goto __next;
case 'd':
case 'i':
if (format_parse_integer(instance, &s1, &len, n) < 0)
goto __error;
s = s2 + 1;
goto __next;
case 'f':
if (format_parse_float(instance, &s1, &len, n) < 0)
goto __error;
s = s2 + 1;
goto __next;
case 's':
if (format_parse_string(instance, &s1, &len, n) < 0)
goto __error;
s = s2 + 1;
goto __next;
case '\0':
goto __end;
default:
lisp_warn(instance, "unknown format char '%c'", *s2);
s = s2 + 1;
goto __next;
}
}
__next:
delete_tree(instance, n);
p1 = cdr(n = p1);
delete_object(instance, n);
n = eval(instance, car(p1));
} while (*s);
__end:
delete_tree(instance, n);
delete_tree(instance, cdr(p1));
delete_object(instance, p1);
delete_tree(instance, p);
if (len > 0) {
p1 = new_string(instance, s1);
free(s1);
} else { } else {
lisp_warn(instance, "expected an integer or float for integer conversion");
p1 = &alsa_lisp_nil; p1 = &alsa_lisp_nil;
} }
delete_tree(instance, p);
return p1; return p1;
} }
/*
* Syntax: (compare-strings str1 start1 end1 str2 start2 end2 /opt-case-insensitive)
* 'str1' is first compared string
* 'start1' is first char (0..)
* 'end1' is last char (0..)
* 'str2' is second compared string
* 'start2' is first char (0..)
* 'end2' is last char (0..)
* /opt-case-insensitive true - case insensitive match
*/
struct alisp_object * F_compare_strings(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p1 = args, * n, * p[7];
char *s1, *s2;
int start1, end1, start2, end2;
for (start1 = 0; start1 < 7; start1++) {
p[start1] = eval(instance, car(p1));
p1 = cdr(n = p1);
delete_object(instance, n);
}
delete_tree(instance, p1);
if (alisp_compare_type(p[0], ALISP_OBJ_STRING)) {
lisp_warn(instance, "compare-strings: first argument must be string\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (alisp_compare_type(p[1], ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "compare-strings: second argument must be integer\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (alisp_compare_type(p[2], ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "compare-strings: third argument must be integer\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (alisp_compare_type(p[3], ALISP_OBJ_STRING)) {
lisp_warn(instance, "compare-strings: fifth argument must be string\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (!alisp_compare_type(p[4], ALISP_OBJ_NIL) &&
!alisp_compare_type(p[4], ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "compare-strings: fourth argument must be integer\n");
p1 = &alsa_lisp_nil;
goto __err;
}
if (!alisp_compare_type(p[5], ALISP_OBJ_NIL) &&
!alisp_compare_type(p[5], ALISP_OBJ_INTEGER)) {
lisp_warn(instance, "compare-strings: sixth argument must be integer\n");
p1 = &alsa_lisp_nil;
goto __err;
}
s1 = p[0]->value.s;
start1 = p[1]->value.i;
end1 = p[2]->value.i;
s2 = p[3]->value.s;
start2 = alisp_compare_type(p[4], ALISP_OBJ_NIL) ? 0 : p[4]->value.i;
end2 = alisp_compare_type(p[5], ALISP_OBJ_NIL) ? start2 + (end1 - start1) : p[5]->value.i;
if (start1 < 0 || start2 < 0 || end1 < 0 || end2 < 0 ||
start1 >= (int)strlen(s1) || start2 >= (int)strlen(s2) ||
(end1 - start1) != (end2 - start2)) {
p1 = &alsa_lisp_nil;
goto __err;
}
if (p[6] != &alsa_lisp_nil) {
while (start1 < end1) {
if (s1[start1] == '\0' ||
s2[start2] == '\0' ||
tolower(s1[start1]) != tolower(s2[start2])) {
p1 = &alsa_lisp_nil;
goto __err;
}
start1++;
start2++;
}
} else {
while (start1 < end1) {
if (s1[start1] == '\0' ||
s2[start2] == '\0' ||
s1[start1] != s2[start2]) {
p1 = &alsa_lisp_nil;
goto __err;
}
start1++;
start2++;
}
}
p1 = &alsa_lisp_t;
__err:
for (start1 = 0; start1 < 7; start1++)
delete_tree(instance, p[start1]);
return p1;
}
/* /*
* Syntax: (assoc key alist) * Syntax: (assoc key alist)
*/ */
@ -2744,9 +2990,10 @@ static struct intrinsic intrinsics[] = {
{ "assoc", F_assoc }, { "assoc", F_assoc },
{ "assq", F_assq }, { "assq", F_assq },
{ "atom", F_atom }, { "atom", F_atom },
{ "call", F_call },
{ "car", F_car }, { "car", F_car },
{ "cdr", F_cdr }, { "cdr", F_cdr },
{ "compare-strings", F_compare_strings },
{ "concat", F_concat },
{ "cond", F_cond }, { "cond", F_cond },
{ "cons", F_cons }, { "cons", F_cons },
{ "defun", F_defun }, { "defun", F_defun },
@ -2754,12 +3001,12 @@ static struct intrinsic intrinsics[] = {
{ "equal", F_equal }, { "equal", F_equal },
{ "eval", F_eval }, { "eval", F_eval },
{ "exfun", F_exfun }, { "exfun", F_exfun },
{ "float", F_float }, { "format", F_format },
{ "funcall", F_funcall },
{ "garbage-collect", F_gc }, { "garbage-collect", F_gc },
{ "gc", F_gc }, { "gc", F_gc },
{ "if", F_if }, { "if", F_if },
{ "include", F_include }, { "include", F_include },
{ "int", F_int },
{ "list", F_list }, { "list", F_list },
{ "not", F_not }, { "not", F_not },
{ "nth", F_nth }, { "nth", F_nth },
@ -2776,9 +3023,11 @@ static struct intrinsic intrinsics[] = {
{ "set", F_set }, { "set", F_set },
{ "setf", F_setq }, { "setf", F_setq },
{ "setq", F_setq }, { "setq", F_setq },
{ "str", F_str },
{ "string=", F_equal },
{ "string-equal", F_equal }, { "string-equal", F_equal },
{ "string-to-float", F_string_to_float },
{ "string-to-integer", F_string_to_integer },
{ "string-to-number", F_string_to_float },
{ "string=", F_equal },
{ "unless", F_unless }, { "unless", F_unless },
{ "unset", F_unset }, { "unset", F_unset },
{ "unsetf", F_unsetq }, { "unsetf", F_unsetq },
@ -2795,7 +3044,7 @@ static int compar(const void *p1, const void *p2)
((struct intrinsic *)p2)->name); ((struct intrinsic *)p2)->name);
} }
static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2) static inline struct alisp_object * eval_cons1(struct alisp_instance *instance, struct alisp_object * p1, struct alisp_object * p2)
{ {
struct alisp_object * p3; struct alisp_object * p3;
struct intrinsic key, *item; struct intrinsic key, *item;
@ -2828,6 +3077,26 @@ static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct
return &alsa_lisp_nil; return &alsa_lisp_nil;
} }
/*
* Syntax: (funcall function args...)
*/
static struct alisp_object * F_funcall(struct alisp_instance *instance, struct alisp_object * args)
{
struct alisp_object * p = eval(instance, car(args)), * p1;
if (!alisp_compare_type(p, ALISP_OBJ_IDENTIFIER) &&
!alisp_compare_type(p, ALISP_OBJ_STRING)) {
lisp_warn(instance, "expected an function name");
delete_tree(instance, p);
delete_tree(instance, cdr(args));
delete_object(instance, args);
return &alsa_lisp_nil;
}
p1 = cdr(args);
delete_object(instance, args);
return eval_cons1(instance, p, p1);
}
static inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p) static inline struct alisp_object * eval_cons(struct alisp_instance *instance, struct alisp_object * p)
{ {
struct alisp_object * p1 = car(p), * p2; struct alisp_object * p1 = car(p), * p2;
@ -2839,6 +3108,8 @@ static inline struct alisp_object * eval_cons(struct alisp_instance *instance, s
p2 = cdr(p); p2 = cdr(p);
delete_object(instance, p); delete_object(instance, p);
return eval_cons1(instance, p1, p2); return eval_cons1(instance, p1, p2);
} else {
delete_tree(instance, p);
} }
return &alsa_lisp_nil; return &alsa_lisp_nil;
@ -2919,6 +3190,7 @@ static int alisp_include_file(struct alisp_instance *instance, const char *filen
} }
} }
snd_input_close(instance->in);
_err: _err:
free(name); free(name);
instance->in = old_in; instance->in = old_in;
@ -3141,12 +3413,21 @@ int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterato
} }
if (res == NULL) if (res == NULL)
err = -ENOMEM; err = -ENOMEM;
if (err == 0 && result) if (err == 0 && result) {
*result = res; *result = res;
} else {
delete_tree(instance, res);
}
return 0; return 0;
} }
void alsa_lisp_result_free(struct alisp_instance *instance,
struct alisp_seq_iterator *result)
{
delete_tree(instance, result);
}
int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id, int alsa_lisp_seq_first(struct alisp_instance *instance, const char *id,
struct alisp_seq_iterator **seq) struct alisp_seq_iterator **seq)
{ {

View file

@ -1,4 +1,11 @@
(defun sndoc_mixer_open (hctl) ;
(princ "sndoc_mixer_open\n") ; SiS SI7018 mixer abstract layer
;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
;
(defun sndoc_mixer_open (hctl pcm)
(princ "sndoc_mixer_open: hctl=" hctl " pcm=" pcm "\n")
0 0
) )

View file

@ -1,4 +1,11 @@
(defun sndop_mixer_open (hctl) ;
(princ "sndop_mixer_open\n") ; SiS SI7018 mixer abstract layer
;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
;
(defun sndop_mixer_open (hctl pcm)
(princ "sndop_mixer_open: hctl=" hctl " pcm=" pcm "\n")
0 0
) )

View file

@ -1,20 +1,20 @@
(setq snd_card_aliases_array (setq snd_card_aliases_array
( (
("YMF724" . "YMF744") ("YMF724" . "YMF744")
("YMF724F" . "YMF744") ("YMF724F" . "YMF744")
("YMF740" . "YMF744") ("YMF740" . "YMF744")
("YMF740C" . "YMF744") ("YMF740C" . "YMF744")
("YMF754" . "YMF744") ("YMF754" . "YMF744")
("CMIPCI" . "CMI8338") ("CMIPCI" . "CMI8338")
("CMI8738" . "CMI8338") ("CMI8738" . "CMI8338")
("CMI8738-MC4" . "CMI8738-MC6") ("CMI8738-MC4" . "CMI8738-MC6")
("E-mu APS" . "EMU10K1") ("E-mu APS" . "EMU10K1")
("GUS Max" . "GUS") ("GUS Max" . "GUS")
("GUS ACE" . "GUS") ("GUS ACE" . "GUS")
("GUS Extreme" . "GUS") ("GUS Extreme" . "GUS")
("AMD InterWave" . "GUS") ("AMD InterWave" . "GUS")
("Dynasonic 3-D" . "GUS") ("Dynasonic 3-D" . "GUS")
("InterWave STB" . "GUS") ("InterWave STB" . "GUS")
) )
) )

View file

@ -1,6 +1,9 @@
; ;
; Toplevel configuration for the ALSA Ordinary Mixer Interface ; Toplevel configuration for the ALSA Ordinary Mixer Interface
; ;
; Copyright (c) 2003 Jaroslav Kysela <perex@suse.cz>
; License: GPL v2 (http://www.gnu.org/licenses/gpl.html)
;
(defun sndo_include (hctl stream) (defun sndo_include (hctl stream)
(setq info (Acall "ctl_card_info" (Acall "hctl_ctl" hctl))) (setq info (Acall "ctl_card_info" (Acall "hctl_ctl" hctl)))
@ -8,7 +11,7 @@
(progn (progn
(setq info (Aresult info)) (setq info (Aresult info))
(setq driver (cdr (assq "driver" (unsetq info)))) (setq driver (cdr (assq "driver" (unsetq info))))
(setq file (+ (path "data") "/alsa/cards/" (snd_card_alias driver) "/sndo" stream "-mixer.alisp")) (setq file (concat (path "data") "/alsa/cards/" (snd_card_alias driver) "/sndo" stream "-mixer.alisp"))
(setq r (include file)) (setq r (include file))
(when (= r -2) (Asyserr "unable to find file " file)) (when (= r -2) (Asyserr "unable to find file " file))
) )
@ -17,36 +20,55 @@
(unsetq info driver file r) (unsetq info driver file r)
) )
(defun sndo_mixer_open_fcn (stream) (defun sndo_mixer_open_fcn (hctl stream pcm)
(setq fcn (+ "sndo" stream "_mixer_open")) (setq fcn (concat "sndo" stream "_mixer_open"))
(setq r (if (exfun fcn) (call fcn hctl) 0)) (setq r (if (exfun fcn) (funcall fcn hctl pcm) 0))
(when (= r 0) (when (= r 0)
(setq hctls (if hctls (cons hctls (cons hctl)) hctl)) (setq hctls (if hctls (cons hctls (cons hctl)) hctl))
) )
(unsetq fcn r) (unsetq fcn r)
) )
(defun sndo_mixer_open_hctl (card stream) (defun sndo_mixer_open_hctl (name stream pcm)
(setq hctl (Acall "hctl_open" (+ "hw:" (str card)) nil)) (setq hctl (Acall "hctl_open" name nil))
(setq r (Aerror hctl)) (setq r (Aerror hctl))
(when (= r 0) (when (= r 0)
(setq hctl (Aresult hctl)) (setq hctl (Aresult hctl))
(setq r (sndo_include hctl stream)) (setq r (sndo_include hctl stream))
(when (= r 0) (setq r (sndo_mixer_open_fcn stream))) (if (= r 0)
(setq r (sndo_mixer_open_fcn hctl stream pcm))
(Acall "hctl_close" hctl)
)
) )
(unsetq hctl r) (unsetq hctl r)
) )
(defun sndo_mixer_open_virtual (pcm stream) (defun sndo_mixer_open_virtual (name stream pcm)
(setq name (Acall "pcm_name" pcm)) (setq file (concat (path "data") "/alsa/virtual/" name "/sndo" stream "-mixer.alisp"))
(setq file (+ (path "data") "/alsa/virtual/" name "/sndo" stream "-mixer.alisp"))
(setq r (include file)) (setq r (include file))
(when (= r -2) (Asyserr "unable to find file " file)) (when (= r -2) (Asyserr "unable to find file " file))
(when (= r 0) (setq r (sndo_mixer_open_fcn stream))) (when (= r 0) (setq r (sndo_mixer_open_fcn nil stream pcm)))
(unsetq name file r) (unsetq file r)
) )
(defun sndo_mixer_open1 (pcm stream) (defun sndo_mixer_open1 (name stream)
(if (compare-strings name 0 2 "hw:" 0 2)
(sndo_mixer_open_hctl name stream nil)
(sndo_mixer_open_virtual name stream nil)
)
)
(defun sndo_mixer_open (pname cname)
(setq r (sndo_mixer_open1 pname "p"))
(when (= r 0) (setq r (sndo_mixer_open1 cname "c")))
(when (!= r 0) (sndo_mixer_close))
(unsetq sndo_mixer_open
sndo_mixer_open_pcm sndo_mixer_open_pcm1
sndo_mixer_open_virtual sndo_mixer_open_fcn
sndo_include r)
)
(defun sndo_mixer_open_pcm1 (pcm stream)
(setq info (Acall "pcm_info" pcm)) (setq info (Acall "pcm_info" pcm))
(setq r (Aerror info)) (setq r (Aerror info))
(when (= r 0) (when (= r 0)
@ -54,19 +76,20 @@
(setq card (cdr (assq "card" info))) (setq card (cdr (assq "card" info)))
(setq r (setq r
(if (< card 0) (if (< card 0)
(sndo_mixer_open_virtual pcm stream) (sndo_mixer_open_virtual (Acall "pcm_name" pcm) stream pcm)
(sndo_mixer_open_hctl card stream) (sndo_mixer_open_hctl (format "hw:%i" card) stream pcm)
) )
) )
) )
(unsetq info card r) (unsetq info card r)
) )
(defun sndo_mixer_open (ppcm cpcm) (defun sndo_mixer_open_pcm (ppcm cpcm)
(setq r (sndo_mixer_open1 ppcm "p")) (setq r (sndo_mixer_open_pcm1 ppcm "p"))
(when (= r 0) (setq r (sndo_mixer_open1 cpcm "c"))) (when (= r 0) (setq r (sndo_mixer_open_pcm1 cpcm "c")))
(when (!= r 0) (sndo_mixer_close)) (when (!= r 0) (sndo_mixer_close))
(unsetq sndo_mixer_open sndo_mixer_open1 (unsetq sndo_mixer_open
sndo_mixer_open_pcm sndo_mixer_open_pcm1
sndo_mixer_open_virtual sndo_mixer_open_fcn sndo_mixer_open_virtual sndo_mixer_open_fcn
sndo_include r) sndo_include r)
) )
@ -74,8 +97,8 @@
(defun sndo_mixer_close1 (hctl stream) (defun sndo_mixer_close1 (hctl stream)
(when hctl (when hctl
(progn (progn
(setq fcn (+ "sndo" stream "_mixer_close")) (setq fcn (concat "sndo" stream "_mixer_close"))
(when (exfun fcn) (call fcn hctl)) (when (exfun fcn) (funcall fcn hctl))
(unsetq fcn) (unsetq fcn)
(Acall "hctl_close" hctl) (Acall "hctl_close" hctl)
) )
@ -88,4 +111,4 @@
(unsetq hctls) (unsetq hctls)
) )
(include (+ (path "data") "/alsa/cards/aliases.alisp")) (include (concat (path "data") "/alsa/cards/aliases.alisp"))

View file

@ -67,18 +67,12 @@ struct sndo_mixer {
int _free_cfg; int _free_cfg;
}; };
/** int sndo_mixer_open1(sndo_mixer_t **pmixer,
* \brief Opens a ordinary mixer instance const char *lisp_fcn,
* \param pmixer Returned ordinary mixer handle const char *lisp_fmt,
* \param playback_pcm handle of the playback PCM const void *parg,
* \param capture_pcm handle of the capture PCM const void *carg,
* \param lconf Local configuration (might be NULL - use global configuration) struct alisp_cfg *lconf)
* \return 0 on success otherwise a negative error code
*/
int sndo_mixer_open(sndo_mixer_t **pmixer,
snd_pcm_t *playback_pcm,
snd_pcm_t *capture_pcm,
struct alisp_cfg *lconf)
{ {
struct alisp_cfg *cfg = lconf; struct alisp_cfg *cfg = lconf;
struct alisp_instance *alisp; struct alisp_instance *alisp;
@ -101,16 +95,16 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
cfg = alsa_lisp_default_cfg(input); cfg = alsa_lisp_default_cfg(input);
if (cfg == NULL) if (cfg == NULL)
return -ENOMEM; return -ENOMEM;
cfg->warning = 1;
#if 0 #if 0
cfg->debug = 1; cfg->debug = 1;
cfg->verbose = 1; cfg->verbose = 1;
cfg->warning = 1;
#endif #endif
} }
err = alsa_lisp(cfg, &alisp); err = alsa_lisp(cfg, &alisp);
if (err < 0) if (err < 0)
goto __error; goto __error;
err = alsa_lisp_function(alisp, &iterator, "sndo_mixer_open", "%ppcm%ppcm", playback_pcm, capture_pcm); err = alsa_lisp_function(alisp, &iterator, lisp_fcn, lisp_fmt, parg, carg);
if (err < 0) { if (err < 0) {
alsa_lisp_free(alisp); alsa_lisp_free(alisp);
goto __error; goto __error;
@ -118,6 +112,7 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
err = alsa_lisp_seq_integer(iterator, &val); err = alsa_lisp_seq_integer(iterator, &val);
if (err == 0 && val < 0) if (err == 0 && val < 0)
err = val; err = val;
alsa_lisp_result_free(alisp, iterator);
if (err < 0) { if (err < 0) {
alsa_lisp_free(alisp); alsa_lisp_free(alisp);
goto __error; goto __error;
@ -157,6 +152,39 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
return err; return err;
} }
/**
* \brief Opens a ordinary mixer instance
* \param pmixer Returned ordinary mixer handle
* \param playback_name name for playback HCTL communication
* \param capture_name name for capture HCTL communication
* \param lconf Local configuration (might be NULL - use global configuration)
* \return 0 on success otherwise a negative error code
*/
int sndo_mixer_open(sndo_mixer_t **pmixer,
const char *playback_name,
const char *capture_name,
struct alisp_cfg *lconf)
{
return sndo_mixer_open1(pmixer, "sndo_mixer_open", "%s%s", playback_name, capture_name, lconf);
}
/**
* \brief Opens a ordinary mixer instance
* \param pmixer Returned ordinary mixer handle
* \param playback_pcm handle of the playback PCM
* \param capture_pcm handle of the capture PCM
* \param lconf Local configuration (might be NULL - use global configuration)
* \return 0 on success otherwise a negative error code
*/
int sndo_mixer_open_pcm(sndo_mixer_t **pmixer,
snd_pcm_t *playback_pcm,
snd_pcm_t *capture_pcm,
struct alisp_cfg *lconf)
{
return sndo_mixer_open1(pmixer, "sndo_mixer_open_pcm", "%ppcm%ppcm", playback_pcm, capture_pcm, lconf);
}
/** /**
* \brief Closes a ordinary mixer instance * \brief Closes a ordinary mixer instance
* \param mixer Ordinary mixer handle to close * \param mixer Ordinary mixer handle to close

View file

@ -27,7 +27,7 @@ int main(int argc, char *argv[])
{"cname", 1, NULL, 'C'}, {"cname", 1, NULL, 'C'},
{NULL, 0, NULL, 0}, {NULL, 0, NULL, 0},
}; };
int err, morehelp; int err, morehelp, result = EXIT_SUCCESS;
char *pname = "default", *cname = "default"; char *pname = "default", *cname = "default";
snd_pcm_t *phandle = NULL, *chandle = NULL; snd_pcm_t *phandle = NULL, *chandle = NULL;
sndo_mixer_t *handle; sndo_mixer_t *handle;
@ -59,7 +59,8 @@ int main(int argc, char *argv[])
err = snd_pcm_open(&phandle, pname, SND_PCM_STREAM_PLAYBACK, 0); err = snd_pcm_open(&phandle, pname, SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) { if (err < 0) {
fprintf(stderr, "Playback PCM open error: %s\n", snd_strerror(err)); fprintf(stderr, "Playback PCM open error: %s\n", snd_strerror(err));
return EXIT_FAILURE; result = EXIT_FAILURE;
goto __end;
} }
} }
@ -69,17 +70,23 @@ int main(int argc, char *argv[])
if (phandle) if (phandle)
snd_pcm_close(phandle); snd_pcm_close(phandle);
fprintf(stderr, "Capture PCM open error: %s\n", snd_strerror(err)); fprintf(stderr, "Capture PCM open error: %s\n", snd_strerror(err));
return EXIT_FAILURE; result = EXIT_FAILURE;
goto __end;
} }
} }
err = sndo_mixer_open(&handle, phandle, chandle, NULL); err = sndo_mixer_open_pcm(&handle, phandle, chandle, NULL);
if (err < 0) { if (err < 0) {
fprintf(stderr, "mixer open error: %s\n", snd_strerror(err)); fprintf(stderr, "mixer open error: %s\n", snd_strerror(err));
return EXIT_FAILURE; result = EXIT_FAILURE;
} else {
sndo_mixer_close(handle);
} }
sndo_mixer_close(handle); __end:
snd_pcm_close(chandle); if (chandle)
snd_pcm_close(phandle); snd_pcm_close(chandle);
return EXIT_SUCCESS; if (phandle)
snd_pcm_close(phandle);
snd_config_update_free_global(); /* to keep valgrind happy */
return result;
} }