]> git.alsa-project.org Git - alsa-lib.git/commitdiff
ALISP update
authorJaroslav Kysela <perex@perex.cz>
Tue, 23 Dec 2003 16:42:55 +0000 (16:42 +0000)
committerJaroslav Kysela <perex@perex.cz>
Tue, 23 Dec 2003 16:42:55 +0000 (16:42 +0000)
 - 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)

alsalisp/test.lisp
include/alisp.h
include/mixer_ordinary.h
src/alisp/alisp.c
src/conf/cards/SI7018/sndoc-mixer.alisp
src/conf/cards/SI7018/sndop-mixer.alisp
src/conf/cards/aliases.alisp
src/conf/sndo-mixer.alisp
src/ordinary_mixer/ordinary_mixer.c
test/omixer.c

index eebb7b7ffbfed3b20513d221560eb0168d12ba1c..99a9340b68fe46c5701fa16e3bb1774b5c5f0cb3 100644 (file)
@@ -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)
 ;
 
 ;
 (atom "one")                   (&check-memory)
 (atom "one" 'two)              (&check-memory)
 
-(call)                         (&check-memory)
+(funcall)                      (&check-memory)
 
 (car)                          (&check-memory)
 (car '(one . two))             (&check-memory)
 (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)
 (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)
 
 (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)
 (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)
 (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)
 (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)
 
index f8423d34a38988b8361337c161869871a3f09c50..4deb4d239e090fa9ad224573f9f666c45c8a17fc 100644 (file)
@@ -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);
index 0c25dc20b7a2c1a5a17deda9002d48aa7a3fb761..db362a50b819d573d83e3ab7342ae44c72235cf3 100644 (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_poll_descriptors_count(sndo_mixer_t *mixer);
 int sndo_mixer_poll_descriptors(sndo_mixer_t *mixer, struct pollfd *pfds, unsigned int space);
index e70b6d216d85b34165a8fa4e64662faabf8ac128..987e2712f9e79fdcb5d13c9d4218895b45eb52ec 100644 (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_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,41 +2470,281 @@ 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)
  */
@@ -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)
 {
index 2bea45c0108cf10de2ccc9a1bee5dd5f8c212165..5f6047ae32de60b7affc2a7e67496aee27f6a90c 100644 (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
 )
index 26dc9ad9ef16a7694c64e7c89535952466f670ad..4c5b65c6a6c8a3ec8842fd7cf571931a71446e68 100644 (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
 )
index 3ab21e76a903fcc0b1a1041bfd981e64d3861229..cff78f7a26192174957a02595fa43174fd3c7519 100644 (file)
@@ -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")
   )
 )
 
index b125b6e7861f5ee07d7b4c3ccd259ce991f4bb6d..adf7c97760913f56cea0d3b44f2710fedcc412ae 100644 (file)
@@ -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))
     )
   (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)
     (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)
     )
   (unsetq hctls)
 )
 
-(include (+ (path "data") "/alsa/cards/aliases.alisp"))
+(include (concat (path "data") "/alsa/cards/aliases.alisp"))
index fe9eb4d5516c07c910f3a0c5b67a76ba123a744e..d5d3c266f1661039f6f57c683a55ad196e64d061 100644 (file)
@@ -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;
@@ -157,6 +152,39 @@ int sndo_mixer_open(sndo_mixer_t **pmixer,
        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
  * \param mixer Ordinary mixer handle to close
index 1f4b2e1cb75e28877c4796d305e400112ae19c16..119fa3313032ca4d0c17c9565689e571202ee347 100644 (file)
@@ -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;
 }