diff options
author | Jaroslav Kysela <perex@perex.cz> | 2003-12-23 16:42:55 +0000 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2003-12-23 16:42:55 +0000 |
commit | d0facfde2b1ef8a55fd277f99e64ff7c6c8e7a90 (patch) | |
tree | 4c94cec07fe32a799385fd49a6b0bff3e35cbd77 | |
parent | beb837bcf77c949313b0dbb2cf54b4e9701f3339 (diff) |
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)
-rw-r--r-- | alsalisp/test.lisp | 84 | ||||
-rw-r--r-- | include/alisp.h | 2 | ||||
-rw-r--r-- | include/mixer_ordinary.h | 3 | ||||
-rw-r--r-- | src/alisp/alisp.c | 583 | ||||
-rw-r--r-- | src/conf/cards/SI7018/sndoc-mixer.alisp | 11 | ||||
-rw-r--r-- | src/conf/cards/SI7018/sndop-mixer.alisp | 11 | ||||
-rw-r--r-- | src/conf/cards/aliases.alisp | 30 | ||||
-rw-r--r-- | src/conf/sndo-mixer.alisp | 67 | ||||
-rw-r--r-- | src/ordinary_mixer/ordinary_mixer.c | 56 | ||||
-rw-r--r-- | test/omixer.c | 25 |
10 files changed, 625 insertions, 247 deletions
diff --git a/alsalisp/test.lisp b/alsalisp/test.lisp index eebb7b7f..99a9340b 100644 --- a/alsalisp/test.lisp +++ b/alsalisp/test.lisp @@ -3,7 +3,7 @@ ; The test is indended to find memory leaks. ; ; 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" 'two) (&check-memory) -(call) (&check-memory) +(funcall) (&check-memory) (car) (&check-memory) (car '(one . two)) (&check-memory) @@ -128,6 +128,13 @@ (cdr) (&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 0) (&check-memory) (cond 0 1) (&check-memory) @@ -160,11 +167,17 @@ (exfun 'abcd) (&check-memory) (exfun 'abcd 'ijkl) (&check-memory) -(float) (&check-memory) -(float 1) (&check-memory) -(float 'a) (&check-memory) -(float "a" "b" "c") (&check-memory) -(float "1.2") (&check-memory) +(format) (&check-memory) +(format 1) (&check-memory) +(format 'a) (&check-memory) +(format "a" "b" "c") (&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) (gc) (&check-memory) @@ -179,12 +192,6 @@ (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 "a") (&check-memory) (list "a" "b") (&check-memory) @@ -267,10 +274,28 @@ (setq a 1) (unsetq a) (&check-memory) (setq a 1 2) (unsetq a) (&check-memory) -(str) (&check-memory) -(str 1) (&check-memory) -(str 1 2 3) (&check-memory) -(str 1.2 1.3) (&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) + +(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= 1) (&check-memory) @@ -279,13 +304,6 @@ (string= "a" "b") (&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 1) (&check-memory) (unless 0 1 2) (&check-memory) @@ -322,27 +340,31 @@ (unsetq abcd) (&check-memory) +(setq abcd (("abcd" . "efgh") ("1234" . "5678"))) +(unsetq abcd) +(&check-memory) + (defun myfun () (princ "a\n")) (exfun 'myfun) (unsetq myfun) (&check-memory) (defun myfun () (princ "a\n")) -(call 'myfun) -(call 'myfun 'aaaaa) +(funcall 'myfun) +(funcall 'myfun 'aaaaa) (unsetq myfun) (&check-memory) (defun myfun (o) (princ o "a\n")) -(call 'myfun) -(call 'myfun 'aaaaa) +(funcall 'myfun) +(funcall 'myfun 'aaaaa) (unsetq myfun) (&check-memory) (defun myfun (o p) (princ o p "\n")) -(call 'myfun) -(call 'myfun 'aaaaa) -(call 'myfun 'aaaaa 'bbbbb) +(funcall 'myfun) +(funcall 'myfun 'aaaaa) +(funcall 'myfun 'aaaaa 'bbbbb) (unsetq myfun) (&check-memory) diff --git a/include/alisp.h b/include/alisp.h index f8423d34..4deb4d23 100644 --- a/include/alisp.h +++ b/include/alisp.h @@ -45,6 +45,8 @@ int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterato __attribute__ ((format (printf, 4, 5))) #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, struct alisp_seq_iterator **seq); int alsa_lisp_seq_next(struct alisp_seq_iterator **seq); diff --git a/include/mixer_ordinary.h b/include/mixer_ordinary.h index 0c25dc20..db362a50 100644 --- a/include/mixer_ordinary.h +++ b/include/mixer_ordinary.h @@ -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_poll_descriptors_count(sndo_mixer_t *mixer); int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space); diff --git a/src/alisp/alisp.c b/src/alisp/alisp.c index e70b6d21..987e2712 100644 --- a/src/alisp/alisp.c +++ b/src/alisp/alisp.c @@ -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_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 *); 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 */ 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) { - if (p == NULL) - return; - if (p == &alsa_lisp_nil || p == &alsa_lisp_t) + if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t) return; if (alisp_compare_type(p, ALISP_OBJ_NIL) || 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) { - if (p == NULL) - return NULL; + if (p == NULL || p == &alsa_lisp_nil || p == &alsa_lisp_t) + return p; if (alisp_get_refs(p) == ALISP_MAX_REFS) { assert(0); 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 alisp_object * p; + struct alisp_object_pair * pair; 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 (j = 0; j <= ALISP_OBJ_LAST_SEARCH; j++) { list_for_each_safe(pos, pos1, &instance->used_objs_list[i][j]) { 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); } } @@ -575,7 +591,7 @@ static int gettoken(struct alisp_instance *instance) instance->thistoken = ALISP_INTEGER; do { __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); if (p == NULL) return instance->thistoken = EOF; @@ -620,7 +636,7 @@ static int gettoken(struct alisp_instance *instance) /* Identifier: [!-/+*%<>=&a-zA-Z_][-/+*%<>=&a-zA-Z_0-9]* */ p = instance->token_buffer; 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); if (p == NULL) return instance->thistoken = EOF; @@ -636,7 +652,7 @@ static int gettoken(struct alisp_instance *instance) /* String: "\""([^"]|"\\".)*"\"" */ p = instance->token_buffer; 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); if (p == NULL) return instance->thistoken = EOF; @@ -683,24 +699,26 @@ static struct alisp_object * parse_form(struct alisp_instance *instance) * Parse a dotted pair notation. */ if (thistoken == '.') { - thistoken = gettoken(instance); + gettoken(instance); if (prev == NULL) { - lisp_error(instance, "unexpected `.'"); + lisp_error(instance, "unexpected '.'"); + __err: + delete_tree(instance, first); return NULL; } prev->value.c.cdr = parse_object(instance, 1); if (prev->value.c.cdr == NULL) - return NULL; + goto __err; if ((thistoken = gettoken(instance)) != ')') { - lisp_error(instance, "expected `)'"); - return NULL; + lisp_error(instance, "expected ')'"); + goto __err; } break; } p = new_object(instance, ALISP_OBJ_CONS); if (p == NULL) - return NULL; + goto __err; if (first == NULL) first = p; @@ -709,7 +727,8 @@ static struct alisp_object * parse_form(struct alisp_instance *instance) p->value.c.car = parse_object(instance, 1); if (p->value.c.car == NULL) - return NULL; + goto __err; + prev = p; } @@ -724,11 +743,11 @@ static struct alisp_object * quote_object(struct alisp_instance *instance, struc struct alisp_object * p; if (obj == NULL) - return NULL; + goto __end1; p = new_object(instance, ALISP_OBJ_CONS); if (p == NULL) - return NULL; + goto __end1; p->value.c.car = new_identifier(instance, "quote"); 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) { delete_object(instance, p->value.c.car); __end: - delete_object(instance, obj); delete_object(instance, p); + __end1: + delete_tree(instance, obj); return NULL; } @@ -898,6 +918,7 @@ static struct alisp_object * unset_object(struct alisp_instance *instance, struc if (!strcmp(p->name, id)) { list_del(&p->list); res = p->value; + free((void *)p->name); free(p); 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) { struct alisp_object * p = args, * p1, * n; + long v = 0; + double f = 0; + int type = ALISP_OBJ_INTEGER; p1 = eval(instance, car(p)); - if (alisp_compare_type(p1, ALISP_OBJ_INTEGER) || - alisp_compare_type(p1, ALISP_OBJ_FLOAT)) { - long v = 0; - double f = 0; - int type = ALISP_OBJ_INTEGER; - for (;;) { - if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) { - if (type == ALISP_OBJ_FLOAT) - f += p1->value.i; - else - 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); + for (;;) { + if (alisp_compare_type(p1, ALISP_OBJ_INTEGER)) { + if (type == ALISP_OBJ_FLOAT) + f += p1->value.i; + else + 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 { - 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)) { - char *str = NULL, *str1; - 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; - } - if (str == NULL) - strcpy(str1, p1->value.s); - else - strcat(str1, p1->value.s); - str = str1; - } 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 (type == ALISP_OBJ_INTEGER) { + return new_integer(instance, v); + } else { + return new_float(instance, f); + } +} + +/* + * Syntax: (concat expr...) + */ +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); - p = cdr(n = p); - delete_object(instance, n); - if (p == &alsa_lisp_nil) - break; - p1 = eval(instance, car(p)); + if (str == NULL) + strcpy(str1, p1->value.s); + else + strcat(str1, p1->value.s); + str = str1; + } 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); free(str); - return p; } else { - lisp_warn(instance, "sum/concat with non-integer or string operand"); - delete_tree(instance, cdr(p)); - delete_object(instance, p); - delete_tree(instance, p1); + p = &alsa_lisp_nil; } - return &alsa_lisp_nil; + return p; } /* @@ -2218,6 +2243,7 @@ static struct alisp_object * F_unsetq(struct alisp_instance *instance, struct al if (p1) delete_tree(instance, p1); p1 = unset_object(instance, car(p)); + delete_tree(instance, car(p)); p = cdr(n = p); delete_object(instance, n); } 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) { - struct alisp_object * p1, * p2, * p3, * p4, * p5; + struct alisp_object * p1, * p2, * p3, * p4; struct alisp_object ** eval_objs, ** save_objs; int i; @@ -2297,9 +2323,8 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a i = 0; while (p3 != &alsa_lisp_nil) { eval_objs[i++] = eval(instance, car(p3)); - p4 = cdr(p3); - delete_object(instance, p3); - p3 = p4; + p3 = cdr(p4 = p3); + delete_object(instance, p4); } /* @@ -2307,48 +2332,49 @@ static struct alisp_object * eval_func(struct alisp_instance *instance, struct a */ i = 0; while (p2 != &alsa_lisp_nil) { - p4 = car(p2); - save_objs[i] = replace_object(instance, p4, eval_objs[i]); + p3 = car(p2); + save_objs[i] = replace_object(instance, p3, eval_objs[i]); 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; + } p2 = cdr(p2); ++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. */ - p2 = car(cdr(p)); + p2 = car(p3); + delete_object(instance, p3); i = 0; while (p2 != &alsa_lisp_nil) { - p4 = car(p2); + p3 = car(p2); if (save_objs[i] == NULL) { - p4 = unset_object(instance, p4); + p3 = unset_object(instance, p3); } else { - p4 = replace_object(instance, p4, save_objs[i]); + p3 = replace_object(instance, p3, save_objs[i]); } i++; - delete_tree(instance, p4); - p2 = cdr(p2); + delete_tree(instance, p3); + delete_tree(instance, car(p2)); + p2 = cdr(p3 = p2); + delete_object(instance, p3); } + _end: if (eval_objs) free(eval_objs); - return p5; + return p4; } else { _delete: delete_tree(instance, args); } 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) @@ -2401,30 +2427,10 @@ struct alisp_object * F_include(struct alisp_instance *instance, struct alisp_ob } /* - * 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)), * 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) + * Syntax: (string-to-integer value) * '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; @@ -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 */ -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; @@ -2464,42 +2470,282 @@ struct alisp_object * F_float(struct alisp_instance *instance, struct alisp_obje return p1; } +static int append_to_string(char **s, int *len, char *from, int size) +{ + if (*len == 0) { + *s = malloc(*len = size + 1); + if (*s == NULL) { + nomem(); + return -ENOMEM; + } + memcpy(*s, from, size); + } else { + *len += size; + *s = realloc(*s, *len); + if (*s == NULL) { + nomem(); + 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: (str value) - * 'value' can be integer, float or string type + * Syntax: (format format value...) + * 'format' is C-like format string */ -struct alisp_object * F_str(struct alisp_instance *instance, struct alisp_object * args) +struct alisp_object * F_format(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 = cdr(args), * n; + char *s, *s1, *s2; + int len; - delete_tree(instance, cdr(args)); 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(); - return NULL; - } - if (alisp_compare_type(p, ALISP_OBJ_INTEGER)) { - snprintf(buf, sizeof(buf), "%ld", p->value.i); - } else { - snprintf(buf, sizeof(buf), "%.f", p->value.f); + 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; + } } - p1 = new_string(instance, buf); - free(buf); + __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 { - lisp_warn(instance, "expected an integer or float for integer conversion"); p1 = &alsa_lisp_nil; } - delete_tree(instance, p); 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) */ struct alisp_object * F_assoc(struct alisp_instance *instance, struct alisp_object * args) @@ -2744,9 +2990,10 @@ static struct intrinsic intrinsics[] = { { "assoc", F_assoc }, { "assq", F_assq }, { "atom", F_atom }, - { "call", F_call }, { "car", F_car }, { "cdr", F_cdr }, + { "compare-strings", F_compare_strings }, + { "concat", F_concat }, { "cond", F_cond }, { "cons", F_cons }, { "defun", F_defun }, @@ -2754,12 +3001,12 @@ static struct intrinsic intrinsics[] = { { "equal", F_equal }, { "eval", F_eval }, { "exfun", F_exfun }, - { "float", F_float }, + { "format", F_format }, + { "funcall", F_funcall }, { "garbage-collect", F_gc }, { "gc", F_gc }, { "if", F_if }, { "include", F_include }, - { "int", F_int }, { "list", F_list }, { "not", F_not }, { "nth", F_nth }, @@ -2776,9 +3023,11 @@ static struct intrinsic intrinsics[] = { { "set", F_set }, { "setf", F_setq }, { "setq", F_setq }, - { "str", F_str }, - { "string=", 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 }, { "unset", F_unset }, { "unsetf", F_unsetq }, @@ -2795,7 +3044,7 @@ static int compar(const void *p1, const void *p2) ((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 intrinsic key, *item; @@ -2828,6 +3077,26 @@ static struct alisp_object * eval_cons1(struct alisp_instance *instance, struct 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) { 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); delete_object(instance, p); return eval_cons1(instance, p1, p2); + } else { + delete_tree(instance, p); } 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: free(name); instance->in = old_in; @@ -3141,12 +3413,21 @@ int alsa_lisp_function(struct alisp_instance *instance, struct alisp_seq_iterato } if (res == NULL) err = -ENOMEM; - if (err == 0 && result) + if (err == 0 && result) { *result = res; + } else { + delete_tree(instance, res); + } 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, struct alisp_seq_iterator **seq) { diff --git a/src/conf/cards/SI7018/sndoc-mixer.alisp b/src/conf/cards/SI7018/sndoc-mixer.alisp index 2bea45c0..5f6047ae 100644 --- a/src/conf/cards/SI7018/sndoc-mixer.alisp +++ b/src/conf/cards/SI7018/sndoc-mixer.alisp @@ -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 ) diff --git a/src/conf/cards/SI7018/sndop-mixer.alisp b/src/conf/cards/SI7018/sndop-mixer.alisp index 26dc9ad9..4c5b65c6 100644 --- a/src/conf/cards/SI7018/sndop-mixer.alisp +++ b/src/conf/cards/SI7018/sndop-mixer.alisp @@ -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 ) diff --git a/src/conf/cards/aliases.alisp b/src/conf/cards/aliases.alisp index 3ab21e76..cff78f7a 100644 --- a/src/conf/cards/aliases.alisp +++ b/src/conf/cards/aliases.alisp @@ -1,20 +1,20 @@ (setq snd_card_aliases_array ( - ("YMF724" . "YMF744") - ("YMF724F" . "YMF744") - ("YMF740" . "YMF744") - ("YMF740C" . "YMF744") - ("YMF754" . "YMF744") - ("CMIPCI" . "CMI8338") - ("CMI8738" . "CMI8338") - ("CMI8738-MC4" . "CMI8738-MC6") - ("E-mu APS" . "EMU10K1") - ("GUS Max" . "GUS") - ("GUS ACE" . "GUS") - ("GUS Extreme" . "GUS") - ("AMD InterWave" . "GUS") - ("Dynasonic 3-D" . "GUS") - ("InterWave STB" . "GUS") + ("YMF724" . "YMF744") + ("YMF724F" . "YMF744") + ("YMF740" . "YMF744") + ("YMF740C" . "YMF744") + ("YMF754" . "YMF744") + ("CMIPCI" . "CMI8338") + ("CMI8738" . "CMI8338") + ("CMI8738-MC4" . "CMI8738-MC6") + ("E-mu APS" . "EMU10K1") + ("GUS Max" . "GUS") + ("GUS ACE" . "GUS") + ("GUS Extreme" . "GUS") + ("AMD InterWave" . "GUS") + ("Dynasonic 3-D" . "GUS") + ("InterWave STB" . "GUS") ) ) diff --git a/src/conf/sndo-mixer.alisp b/src/conf/sndo-mixer.alisp index b125b6e7..adf7c977 100644 --- a/src/conf/sndo-mixer.alisp +++ b/src/conf/sndo-mixer.alisp @@ -1,6 +1,9 @@ ; ; 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) (setq info (Acall "ctl_card_info" (Acall "hctl_ctl" hctl))) @@ -8,7 +11,7 @@ (progn (setq info (Aresult 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)) (when (= r -2) (Asyserr "unable to find file " file)) ) @@ -17,36 +20,55 @@ (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)) +(defun sndo_mixer_open_fcn (hctl stream pcm) + (setq fcn (concat "sndo" stream "_mixer_open")) + (setq r (if (exfun fcn) (funcall fcn hctl pcm) 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)) +(defun sndo_mixer_open_hctl (name stream pcm) + (setq hctl (Acall "hctl_open" name 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))) + (if (= r 0) + (setq r (sndo_mixer_open_fcn hctl stream pcm)) + (Acall "hctl_close" hctl) + ) ) (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")) +(defun sndo_mixer_open_virtual (name stream pcm) + (setq file (concat (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) + (when (= r 0) (setq r (sndo_mixer_open_fcn nil stream pcm))) + (unsetq file r) +) + +(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_open1 (pcm stream) +(defun sndo_mixer_open_pcm1 (pcm stream) (setq info (Acall "pcm_info" pcm)) (setq r (Aerror info)) (when (= r 0) @@ -54,19 +76,20 @@ (setq card (cdr (assq "card" info))) (setq r (if (< card 0) - (sndo_mixer_open_virtual pcm stream) - (sndo_mixer_open_hctl card stream) + (sndo_mixer_open_virtual (Acall "pcm_name" pcm) stream pcm) + (sndo_mixer_open_hctl (format "hw:%i" card) stream pcm) ) ) ) (unsetq info card r) ) -(defun sndo_mixer_open (ppcm cpcm) - (setq r (sndo_mixer_open1 ppcm "p")) - (when (= r 0) (setq r (sndo_mixer_open1 cpcm "c"))) +(defun sndo_mixer_open_pcm (ppcm cpcm) + (setq r (sndo_mixer_open_pcm1 ppcm "p")) + (when (= r 0) (setq r (sndo_mixer_open_pcm1 cpcm "c"))) (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_include r) ) @@ -74,8 +97,8 @@ (defun sndo_mixer_close1 (hctl stream) (when hctl (progn - (setq fcn (+ "sndo" stream "_mixer_close")) - (when (exfun fcn) (call fcn hctl)) + (setq fcn (concat "sndo" stream "_mixer_close")) + (when (exfun fcn) (funcall fcn hctl)) (unsetq fcn) (Acall "hctl_close" hctl) ) @@ -88,4 +111,4 @@ (unsetq hctls) ) -(include (+ (path "data") "/alsa/cards/aliases.alisp")) +(include (concat (path "data") "/alsa/cards/aliases.alisp")) diff --git a/src/ordinary_mixer/ordinary_mixer.c b/src/ordinary_mixer/ordinary_mixer.c index fe9eb4d5..d5d3c266 100644 --- a/src/ordinary_mixer/ordinary_mixer.c +++ b/src/ordinary_mixer/ordinary_mixer.c @@ -67,18 +67,12 @@ struct sndo_mixer { int _free_cfg; }; -/** - * \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(sndo_mixer_t **pmixer, - snd_pcm_t *playback_pcm, - snd_pcm_t *capture_pcm, - struct alisp_cfg *lconf) +int sndo_mixer_open1(sndo_mixer_t **pmixer, + const char *lisp_fcn, + const char *lisp_fmt, + const void *parg, + const void *carg, + struct alisp_cfg *lconf) { struct alisp_cfg *cfg = lconf; struct alisp_instance *alisp; @@ -101,16 +95,16 @@ int sndo_mixer_open(sndo_mixer_t **pmixer, cfg = alsa_lisp_default_cfg(input); if (cfg == NULL) return -ENOMEM; + cfg->warning = 1; #if 0 cfg->debug = 1; cfg->verbose = 1; - cfg->warning = 1; #endif } err = alsa_lisp(cfg, &alisp); if (err < 0) 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) { alsa_lisp_free(alisp); goto __error; @@ -118,6 +112,7 @@ int sndo_mixer_open(sndo_mixer_t **pmixer, err = alsa_lisp_seq_integer(iterator, &val); if (err == 0 && val < 0) err = val; + alsa_lisp_result_free(alisp, iterator); if (err < 0) { alsa_lisp_free(alisp); goto __error; @@ -158,6 +153,39 @@ int sndo_mixer_open(sndo_mixer_t **pmixer, } /** + * \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 * \param mixer Ordinary mixer handle to close * \return 0 on success otherwise a negative error code diff --git a/test/omixer.c b/test/omixer.c index 1f4b2e1c..119fa331 100644 --- a/test/omixer.c +++ b/test/omixer.c @@ -27,7 +27,7 @@ int main(int argc, char *argv[]) {"cname", 1, NULL, 'C'}, {NULL, 0, NULL, 0}, }; - int err, morehelp; + int err, morehelp, result = EXIT_SUCCESS; char *pname = "default", *cname = "default"; snd_pcm_t *phandle = NULL, *chandle = NULL; 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); if (err < 0) { 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) snd_pcm_close(phandle); 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) { 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); - snd_pcm_close(chandle); - snd_pcm_close(phandle); - return EXIT_SUCCESS; + __end: + if (chandle) + snd_pcm_close(chandle); + if (phandle) + snd_pcm_close(phandle); + snd_config_update_free_global(); /* to keep valgrind happy */ + return result; } |